• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 #ifndef LOG_TAG
16 #define LOG_TAG "NapiAudioRenderer"
17 #endif
18 
19 #include "napi_audio_renderer.h"
20 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
21 #include "errors.h"
22 #else
23 #ifdef FEATURE_HIVIEW_ENABLE
24 #include "xpower_event_js.h"
25 #endif
26 #endif
27 #include "napi_param_utils.h"
28 #include "napi_audio_error.h"
29 #include "napi_audio_enum.h"
30 #include "napi_audio_renderer_callback.h"
31 #include "napi_renderer_position_callback.h"
32 #include "napi_renderer_data_request_callback.h"
33 #include "napi_renderer_period_position_callback.h"
34 #include "napi_audio_renderer_write_data_callback.h"
35 #include "napi_audio_renderer_device_change_callback.h"
36 #include "napi_audio_renderer_policy_service_died_callback.h"
37 
38 namespace OHOS {
39 namespace AudioStandard {
40 static __thread napi_ref g_rendererConstructor = nullptr;
41 mutex NapiAudioRenderer::createMutex_;
42 int32_t NapiAudioRenderer::isConstructSuccess_ = SUCCESS;
43 std::unique_ptr<AudioRendererOptions> NapiAudioRenderer::sRendererOptions_ = nullptr;
44 static constexpr double MIN_LOUDNESS_GAIN_IN_DOUBLE = -90.0;
45 static constexpr double MAX_LOUDNESS_GAIN_IN_DOUBLE = 24.0;
46 
NapiAudioRenderer()47 NapiAudioRenderer::NapiAudioRenderer()
48     : audioRenderer_(nullptr), contentType_(CONTENT_TYPE_MUSIC), streamUsage_(STREAM_USAGE_MEDIA), env_(nullptr) {}
49 
~NapiAudioRenderer()50 NapiAudioRenderer::~NapiAudioRenderer()
51 {
52     if (audioRenderer_ != nullptr) {
53         bool ret = audioRenderer_->Release();
54         CHECK_AND_RETURN_LOG(ret, "AudioRenderer release fail");
55         audioRenderer_ = nullptr;
56         AUDIO_INFO_LOG("Proactively release audioRenderer");
57     }
58 }
59 
Destructor(napi_env env,void * nativeObject,void * finalizeHint)60 void NapiAudioRenderer::Destructor(napi_env env, void *nativeObject, void *finalizeHint)
61 {
62     if (nativeObject == nullptr) {
63         AUDIO_WARNING_LOG("Native object is null");
64         return;
65     }
66     auto obj = static_cast<NapiAudioRenderer *>(nativeObject);
67     ObjectRefMap<NapiAudioRenderer>::DecreaseRef(obj);
68     AUDIO_INFO_LOG("Decrease obj count");
69 }
70 
InitNapiAudioRenderer(napi_env env,napi_value & constructor)71 napi_status NapiAudioRenderer::InitNapiAudioRenderer(napi_env env, napi_value &constructor)
72 {
73     napi_property_descriptor audio_renderer_properties[] = {
74         DECLARE_NAPI_FUNCTION("setRenderRate", SetRenderRate),
75         DECLARE_NAPI_FUNCTION("getRenderRate", GetRenderRate),
76         DECLARE_NAPI_FUNCTION("getRenderRateSync", GetRenderRateSync),
77         DECLARE_NAPI_FUNCTION("setRendererSamplingRate", SetRendererSamplingRate),
78         DECLARE_NAPI_FUNCTION("getRendererSamplingRate", GetRendererSamplingRate),
79         DECLARE_NAPI_FUNCTION("start", Start),
80         DECLARE_NAPI_FUNCTION("write", Write),
81         DECLARE_NAPI_FUNCTION("getAudioTime", GetAudioTime),
82         DECLARE_NAPI_FUNCTION("getAudioTimeSync", GetAudioTimeSync),
83         DECLARE_NAPI_FUNCTION("drain", Drain),
84         DECLARE_NAPI_FUNCTION("flush", Flush),
85         DECLARE_NAPI_FUNCTION("pause", Pause),
86         DECLARE_NAPI_FUNCTION("stop", Stop),
87         DECLARE_NAPI_FUNCTION("release", Release),
88         DECLARE_NAPI_FUNCTION("getBufferSize", GetBufferSize),
89         DECLARE_NAPI_FUNCTION("getBufferSizeSync", GetBufferSizeSync),
90         DECLARE_NAPI_FUNCTION("getAudioStreamId", GetAudioStreamId),
91         DECLARE_NAPI_FUNCTION("getAudioStreamIdSync", GetAudioStreamIdSync),
92         DECLARE_NAPI_FUNCTION("setVolume", SetVolume),
93         DECLARE_NAPI_FUNCTION("getVolume", GetVolume),
94         DECLARE_NAPI_FUNCTION("setLoudnessGain", SetLoudnessGain),
95         DECLARE_NAPI_FUNCTION("getLoudnessGain", GetLoudnessGain),
96         DECLARE_NAPI_FUNCTION("getRendererInfo", GetRendererInfo),
97         DECLARE_NAPI_FUNCTION("getRendererInfoSync", GetRendererInfoSync),
98         DECLARE_NAPI_FUNCTION("getStreamInfo", GetStreamInfo),
99         DECLARE_NAPI_FUNCTION("getStreamInfoSync", GetStreamInfoSync),
100         DECLARE_NAPI_FUNCTION("setInterruptMode", SetInterruptMode),
101         DECLARE_NAPI_FUNCTION("setInterruptModeSync", SetInterruptModeSync),
102         DECLARE_NAPI_FUNCTION("getMinStreamVolume", GetMinStreamVolume),
103         DECLARE_NAPI_FUNCTION("getMinStreamVolumeSync", GetMinStreamVolumeSync),
104         DECLARE_NAPI_FUNCTION("getMaxStreamVolume", GetMaxStreamVolume),
105         DECLARE_NAPI_FUNCTION("getMaxStreamVolumeSync", GetMaxStreamVolumeSync),
106         DECLARE_NAPI_FUNCTION("getCurrentOutputDevices", GetCurrentOutputDevices),
107         DECLARE_NAPI_FUNCTION("getCurrentOutputDevicesSync", GetCurrentOutputDevicesSync),
108         DECLARE_NAPI_FUNCTION("getUnderflowCount", GetUnderflowCount),
109         DECLARE_NAPI_FUNCTION("getUnderflowCountSync", GetUnderflowCountSync),
110         DECLARE_NAPI_FUNCTION("getAudioEffectMode", GetAudioEffectMode),
111         DECLARE_NAPI_FUNCTION("setAudioEffectMode", SetAudioEffectMode),
112         DECLARE_NAPI_FUNCTION("setChannelBlendMode", SetChannelBlendMode),
113         DECLARE_NAPI_FUNCTION("setVolumeWithRamp", SetVolumeWithRamp),
114         DECLARE_NAPI_FUNCTION("setSpeed", SetSpeed),
115         DECLARE_NAPI_FUNCTION("getSpeed", GetSpeed),
116         DECLARE_NAPI_GETTER("state", GetState),
117         DECLARE_NAPI_FUNCTION("on", On),
118         DECLARE_NAPI_FUNCTION("off", Off),
119         DECLARE_NAPI_FUNCTION("setSilentModeAndMixWithOthers", SetSilentModeAndMixWithOthers),
120         DECLARE_NAPI_FUNCTION("getSilentModeAndMixWithOthers", GetSilentModeAndMixWithOthers),
121         DECLARE_NAPI_FUNCTION("getAudioTimestampInfo", GetAudioTimestampInfo),
122         DECLARE_NAPI_FUNCTION("getAudioTimestampInfoSync", GetAudioTimestampInfoSync),
123         DECLARE_NAPI_FUNCTION("setDefaultOutputDevice", SetDefaultOutputDevice),
124     };
125 
126     napi_status status = napi_define_class(env, NAPI_AUDIO_RENDERER_CLASS_NAME.c_str(),
127         NAPI_AUTO_LENGTH, Construct, nullptr,
128         sizeof(audio_renderer_properties) / sizeof(audio_renderer_properties[PARAM0]),
129         audio_renderer_properties, &constructor);
130     return status;
131 }
132 
Init(napi_env env,napi_value exports)133 napi_value NapiAudioRenderer::Init(napi_env env, napi_value exports)
134 {
135     napi_status status;
136     napi_value constructor;
137     napi_value result = nullptr;
138     const int32_t refCount = 1;
139     napi_get_undefined(env, &result);
140 
141     napi_property_descriptor static_prop[] = {
142         DECLARE_NAPI_STATIC_FUNCTION("createAudioRenderer", CreateAudioRenderer),
143         DECLARE_NAPI_STATIC_FUNCTION("createAudioRendererSync", CreateAudioRendererSync),
144     };
145 
146     status = InitNapiAudioRenderer(env, constructor);
147     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "InitNapiAudioRenderer fail");
148 
149     status = napi_create_reference(env, constructor, refCount, &g_rendererConstructor);
150     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_reference fail");
151     status = napi_set_named_property(env, exports, NAPI_AUDIO_RENDERER_CLASS_NAME.c_str(), constructor);
152     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_set_named_property fail");
153     status = napi_define_properties(env, exports,
154         sizeof(static_prop) / sizeof(static_prop[PARAM0]), static_prop);
155     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_define_properties fail");
156     return exports;
157 }
158 
GetCallback(size_t argc,napi_value * argv)159 napi_value NapiAudioRenderer::GetCallback(size_t argc, napi_value *argv)
160 {
161     napi_value callback = nullptr;
162 
163     if (argc == ARGS_TWO) {
164         callback = argv[PARAM1];
165     }
166     return callback;
167 }
168 
169 template <typename T>
GetRendererNapiCallback(napi_value callback,const std::string & cbName,std::list<std::shared_ptr<NapiAudioRendererCallbackInner>> audioRendererCallbacks,std::shared_ptr<T> * cb)170 static void GetRendererNapiCallback(napi_value callback, const std::string &cbName,
171     std::list<std::shared_ptr<NapiAudioRendererCallbackInner>> audioRendererCallbacks, std::shared_ptr<T> *cb)
172 {
173     if (audioRendererCallbacks.size() == 0) {
174         AUDIO_ERR_LOG("no callback to get");
175         return;
176     }
177     for (auto &iter : audioRendererCallbacks) {
178         if (!iter->CheckIfTargetCallbackName(cbName)) {
179             continue;
180         }
181         std::shared_ptr<T> temp = std::static_pointer_cast<T>(iter);
182         if (temp->ContainSameJsCallbackInner(cbName, callback)) {
183             *cb = temp;
184             return;
185         }
186     }
187 }
188 
189 template <typename T>
UnregisterAudioRendererSingletonCallbackTemplate(napi_env env,napi_value callback,const std::string & cbName,std::shared_ptr<T> cb,std::function<int32_t (std::shared_ptr<T> callbackPtr,napi_value callback)> removeFunction=nullptr)190 static void UnregisterAudioRendererSingletonCallbackTemplate(napi_env env, napi_value callback,
191     const std::string &cbName, std::shared_ptr<T> cb,
192     std::function<int32_t(std::shared_ptr<T> callbackPtr, napi_value callback)> removeFunction = nullptr)
193 {
194     if (callback != nullptr) {
195         CHECK_AND_RETURN_LOG(cb->ContainSameJsCallbackInner(cbName, callback), "callback not exists!");
196     }
197     cb->RemoveCallbackReference(cbName, env, callback);
198 
199     if (removeFunction == nullptr) {
200         return;
201     }
202     int32_t ret = removeFunction(cb, callback);
203     CHECK_AND_RETURN_LOG(ret == SUCCESS, "Unset of Renderer info change call failed");
204     return;
205 }
206 
CreateRendererFailed()207 void NapiAudioRenderer::CreateRendererFailed()
208 {
209     NapiAudioRenderer::isConstructSuccess_ = NAPI_ERR_SYSTEM;
210     if (AudioRenderer::CheckMaxRendererInstances() == ERR_OVERFLOW) {
211         NapiAudioRenderer::isConstructSuccess_ = NAPI_ERR_STREAM_LIMIT;
212     }
213     AUDIO_ERR_LOG("Renderer Create failed %{public}d", isConstructSuccess_);
214 }
215 
CreateAudioRendererNativeObject(napi_env env)216 unique_ptr<NapiAudioRenderer> NapiAudioRenderer::CreateAudioRendererNativeObject(napi_env env)
217 {
218     unique_ptr<NapiAudioRenderer> rendererNapi = make_unique<NapiAudioRenderer>();
219     CHECK_AND_RETURN_RET_LOG(rendererNapi != nullptr, nullptr, "No memory");
220 
221     rendererNapi->env_ = env;
222     rendererNapi->contentType_ = sRendererOptions_->rendererInfo.contentType;
223     rendererNapi->streamUsage_ = sRendererOptions_->rendererInfo.streamUsage;
224 
225     AudioRendererOptions rendererOptions = *sRendererOptions_;
226     /* NapiAudioRenderer not support other rendererFlags, only support flag 0 */
227     if (rendererOptions.rendererInfo.rendererFlags != 0) {
228         rendererOptions.rendererInfo.rendererFlags = 0;
229     }
230     /* Set isOffloadAllowed before renderer creation when setOffloadAllowed is disabled.*/
231     if (rendererNapi->streamUsage_ == STREAM_USAGE_UNKNOWN) {
232         AUDIO_WARNING_LOG("stream usage is unknown, do not allow to use offload output");
233         rendererOptions.rendererInfo.isOffloadAllowed = false;
234     }
235     rendererOptions.rendererInfo.playerType = PLAYER_TYPE_ARKTS_AUDIO_RENDERER;
236 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
237     rendererNapi->audioRenderer_ = AudioRenderer::CreateRenderer(rendererOptions);
238 #else
239     std::string cacheDir = "";
240     rendererNapi->audioRenderer_ = AudioRenderer::Create(cacheDir, rendererOptions);
241 #endif
242     if (rendererNapi->audioRenderer_ == nullptr) {
243         CreateRendererFailed();
244         rendererNapi.release();
245         return nullptr;
246     }
247 
248     if (rendererNapi->audioRenderer_ != nullptr && rendererNapi->callbackNapi_ == nullptr) {
249         rendererNapi->callbackNapi_ = std::make_shared<NapiAudioRendererCallback>(env);
250         CHECK_AND_RETURN_RET_LOG(rendererNapi->callbackNapi_ != nullptr, nullptr, "No memory");
251         int32_t ret = rendererNapi->audioRenderer_->SetRendererCallback(rendererNapi->callbackNapi_);
252         CHECK_AND_RETURN_RET_LOG(!ret, rendererNapi, "Construct SetRendererCallback failed");
253     }
254     ObjectRefMap<NapiAudioRenderer>::Insert(rendererNapi.get());
255     return rendererNapi;
256 }
257 
Construct(napi_env env,napi_callback_info info)258 napi_value NapiAudioRenderer::Construct(napi_env env, napi_callback_info info)
259 {
260     napi_value result = nullptr;
261     napi_get_undefined(env, &result);
262 
263     size_t argCount = ARGS_TWO;
264     napi_value thisVar = nullptr;
265     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
266     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
267 
268     unique_ptr<NapiAudioRenderer> rendererNapi = CreateAudioRendererNativeObject(env);
269     CHECK_AND_RETURN_RET_LOG(rendererNapi != nullptr, result, "failed to CreateAudioRendererNativeObject");
270 
271     status = napi_wrap(env, thisVar, static_cast<void*>(rendererNapi.get()),
272         NapiAudioRenderer::Destructor, nullptr, nullptr);
273     if (status != napi_ok) {
274         ObjectRefMap<NapiAudioRenderer>::Erase(rendererNapi.get());
275         return result;
276     }
277     rendererNapi.release();
278     return thisVar;
279 }
280 
CheckContextStatus(std::shared_ptr<AudioRendererAsyncContext> context)281 bool NapiAudioRenderer::CheckContextStatus(std::shared_ptr<AudioRendererAsyncContext> context)
282 {
283     CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context object is nullptr.");
284     if (context->native == nullptr) {
285         context->SignError(NAPI_ERR_SYSTEM);
286         return false;
287     }
288     return true;
289 }
290 
CheckAudioRendererStatus(NapiAudioRenderer * napi,std::shared_ptr<AudioRendererAsyncContext> context)291 bool NapiAudioRenderer::CheckAudioRendererStatus(NapiAudioRenderer *napi,
292     std::shared_ptr<AudioRendererAsyncContext> context)
293 {
294     CHECK_AND_RETURN_RET_LOG(napi != nullptr, false, "napi object is nullptr.");
295     if (napi->audioRenderer_ == nullptr) {
296         context->SignError(NAPI_ERR_SYSTEM);
297         return false;
298     }
299     return true;
300 }
301 
GetParamWithSync(const napi_env & env,napi_callback_info info,size_t & argc,napi_value * args)302 NapiAudioRenderer* NapiAudioRenderer::GetParamWithSync(const napi_env &env, napi_callback_info info,
303     size_t &argc, napi_value *args)
304 {
305     NapiAudioRenderer *napiAudioRenderer = nullptr;
306     napi_value jsThis = nullptr;
307 
308     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
309     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr,
310         "GetParamWithSync fail to napi_get_cb_info");
311 
312     status = napi_unwrap(env, jsThis, (void **)&napiAudioRenderer);
313     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "napi_unwrap failed");
314     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr && napiAudioRenderer->audioRenderer_ != nullptr,
315         napiAudioRenderer, "GetParamWithSync fail to napi_unwrap");
316     return napiAudioRenderer;
317 }
318 
CreateAudioRendererWrapper(napi_env env,const AudioRendererOptions rendererOptions)319 napi_value NapiAudioRenderer::CreateAudioRendererWrapper(napi_env env, const AudioRendererOptions rendererOptions)
320 {
321     lock_guard<mutex> lock(createMutex_);
322     napi_value result = nullptr;
323     napi_value constructor;
324 
325     napi_status status = napi_get_reference_value(env, g_rendererConstructor, &constructor);
326     if (status != napi_ok) {
327         AUDIO_ERR_LOG("Failed in CreateAudioRendererWrapper, %{public}d", status);
328         goto fail;
329     }
330 
331     sRendererOptions_ = make_unique<AudioRendererOptions>();
332     CHECK_AND_RETURN_RET_LOG(sRendererOptions_ != nullptr, result, "sRendererOptions_ create failed");
333     *sRendererOptions_ = rendererOptions;
334     status = napi_new_instance(env, constructor, 0, nullptr, &result);
335     if (status != napi_ok) {
336         AUDIO_ERR_LOG("napi_new_instance failed, status:%{public}d", status);
337         goto fail;
338     }
339     return result;
340 
341 fail:
342     napi_get_undefined(env, &result);
343     return result;
344 }
345 
CreateAudioRenderer(napi_env env,napi_callback_info info)346 napi_value NapiAudioRenderer::CreateAudioRenderer(napi_env env, napi_callback_info info)
347 {
348     auto context = std::make_shared<AudioRendererAsyncContext>();
349     if (context == nullptr) {
350         AUDIO_ERR_LOG("CreateAudioRenderer failed : no memory");
351         NapiAudioError::ThrowError(env, "CreateAudioRenderer failed : no memory",
352             NAPI_ERR_NO_MEMORY);
353         return NapiParamUtils::GetUndefinedValue(env);
354     }
355 
356     auto inputParser = [env, context](size_t argc, napi_value *argv) {
357         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
358             NAPI_ERR_INVALID_PARAM);
359         context->status = NapiParamUtils::GetRendererOptions(env, &context->rendererOptions, argv[PARAM0]);
360         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get audioRendererRate failed",
361             NAPI_ERR_INVALID_PARAM);
362     };
363     context->GetCbInfo(env, info, inputParser);
364 
365     auto complete = [env, context](napi_value &output) {
366         output = CreateAudioRendererWrapper(env, context->rendererOptions);
367 
368         // IsConstructSuccess_ Used when creating a renderer fails.
369         if (isConstructSuccess_ != SUCCESS) {
370             context->SignError(isConstructSuccess_);
371             isConstructSuccess_ = SUCCESS;
372         }
373     };
374 
375     return NapiAsyncWork::Enqueue(env, context, "CreateAudioRenderer", nullptr, complete);
376 }
377 
CreateAudioRendererSync(napi_env env,napi_callback_info info)378 napi_value NapiAudioRenderer::CreateAudioRendererSync(napi_env env, napi_callback_info info)
379 {
380     AUDIO_INFO_LOG("CreateAudioRendererSync");
381     size_t argc = ARGS_ONE;
382     napi_value argv[ARGS_ONE] = {};
383     napi_status status = NapiParamUtils::GetParam(env, info, argc, argv);
384     CHECK_AND_RETURN_RET_LOG((argc == ARGS_ONE) && (status == napi_ok),
385         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "GetParam failed");
386 
387     napi_valuetype valueType = napi_undefined;
388     napi_typeof(env, argv[PARAM0], &valueType);
389     CHECK_AND_RETURN_RET_LOG(valueType == napi_object,
390         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "valueType invaild");
391 
392     AudioRendererOptions rendererOptions;
393     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::GetRendererOptions(env, &rendererOptions, argv[PARAM0]) == napi_ok,
394         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM), "GetRendererOptions failed");
395 
396     return NapiAudioRenderer::CreateAudioRendererWrapper(env, rendererOptions);
397 }
398 
SetRenderRate(napi_env env,napi_callback_info info)399 napi_value NapiAudioRenderer::SetRenderRate(napi_env env, napi_callback_info info)
400 {
401     auto context = std::make_shared<AudioRendererAsyncContext>();
402     if (context == nullptr) {
403         AUDIO_ERR_LOG("SetRenderRate failed : no memory");
404         NapiAudioError::ThrowError(env, "SetRenderRate failed : no memory", NAPI_ERR_NO_MEMORY);
405         return NapiParamUtils::GetUndefinedValue(env);
406     }
407 
408     auto inputParser = [env, context](size_t argc, napi_value *argv) {
409         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
410             NAPI_ERR_INVALID_PARAM);
411         context->status = NapiParamUtils::GetValueInt32(env, context->audioRendererRate, argv[PARAM0]);
412         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get audioRendererRate failed",
413             NAPI_ERR_INVALID_PARAM);
414     };
415     context->GetCbInfo(env, info, inputParser);
416 
417     auto executor = [context]() {
418         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
419         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
420         ObjectRefMap objectGuard(obj);
421         auto *napiAudioRenderer = objectGuard.GetPtr();
422         AudioRendererRate audioRenderRate = static_cast<AudioRendererRate>(context->audioRendererRate);
423         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
424             "context object state is error.");
425         int32_t audioClientInvalidParamsErr = -2;
426         context->intValue = napiAudioRenderer->audioRenderer_->SetRenderRate(audioRenderRate);
427         if (context->intValue != SUCCESS) {
428             if (context->intValue == audioClientInvalidParamsErr) {
429                 context->SignError(NAPI_ERR_UNSUPPORTED);
430             } else {
431                 context->SignError(NAPI_ERR_SYSTEM);
432             }
433         }
434     };
435     auto complete = [env](napi_value &output) {
436         output = NapiParamUtils::GetUndefinedValue(env);
437     };
438     return NapiAsyncWork::Enqueue(env, context, "SetRenderRate", executor, complete);
439 }
440 
GetRenderRate(napi_env env,napi_callback_info info)441 napi_value NapiAudioRenderer::GetRenderRate(napi_env env, napi_callback_info info)
442 {
443     auto context = std::make_shared<AudioRendererAsyncContext>();
444     if (context == nullptr) {
445         AUDIO_ERR_LOG("GetRenderRate failed : no memory");
446         NapiAudioError::ThrowError(env, "GetRenderRate failed : no memory", NAPI_ERR_NO_MEMORY);
447         return NapiParamUtils::GetUndefinedValue(env);
448     }
449 
450     context->GetCbInfo(env, info);
451 
452     auto executor = [context]() {
453         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
454         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
455         ObjectRefMap objectGuard(obj);
456         auto *napiAudioRenderer = objectGuard.GetPtr();
457         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
458             "context object state is error.");
459         context->intValue = napiAudioRenderer->audioRenderer_->GetRenderRate();
460     };
461     auto complete = [env, context](napi_value &output) {
462         NapiParamUtils::SetValueInt32(env, context->intValue, output);
463     };
464     return NapiAsyncWork::Enqueue(env, context, "GetRenderRate", executor, complete);
465 }
466 
GetRenderRateSync(napi_env env,napi_callback_info info)467 napi_value NapiAudioRenderer::GetRenderRateSync(napi_env env, napi_callback_info info)
468 {
469     napi_value result = nullptr;
470     size_t argc = PARAM0;
471     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
472     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
473         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
474 
475     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
476     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
477     AudioRendererRate rendererRate = napiAudioRenderer->audioRenderer_->GetRenderRate();
478     NapiParamUtils::SetValueInt32(env, static_cast<int32_t>(rendererRate), result);
479     return result;
480 }
481 
SetRendererSamplingRate(napi_env env,napi_callback_info info)482 napi_value NapiAudioRenderer::SetRendererSamplingRate(napi_env env, napi_callback_info info)
483 {
484     auto context = std::make_shared<AudioRendererAsyncContext>();
485     if (context == nullptr) {
486         AUDIO_ERR_LOG("SetRendererSamplingRate failed : no memory");
487         NapiAudioError::ThrowError(env, "SetRendererSamplingRate failed : no memory",
488             NAPI_ERR_NO_MEMORY);
489         return NapiParamUtils::GetUndefinedValue(env);
490     }
491 
492     auto inputParser = [env, context](size_t argc, napi_value *argv) {
493         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
494             NAPI_ERR_INVALID_PARAM);
495         context->status = NapiParamUtils::GetValueUInt32(env, context->rendererSampleRate, argv[PARAM0]);
496         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get RendererSamplingRate failed",
497             NAPI_ERR_INVALID_PARAM);
498     };
499 
500     context->GetCbInfo(env, info, inputParser);
501 
502     auto executor = [context]() {
503         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
504         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
505         ObjectRefMap objectGuard(obj);
506         auto *napiAudioRenderer = objectGuard.GetPtr();
507         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
508             "context object state is error.");
509         if (context->rendererSampleRate <= 0) {
510             context->SignError(NAPI_ERR_UNSUPPORTED);
511             return;
512         }
513         context->intValue =
514             napiAudioRenderer->audioRenderer_->SetRendererSamplingRate(context->rendererSampleRate);
515         if (context->intValue != SUCCESS) {
516             context->SignError(NAPI_ERR_SYSTEM);
517         }
518     };
519 
520     auto complete = [env](napi_value &output) {
521         output = NapiParamUtils::GetUndefinedValue(env);
522     };
523     return NapiAsyncWork::Enqueue(env, context, "SetRendererSamplingRate", executor, complete);
524 }
525 
GetRendererSamplingRate(napi_env env,napi_callback_info info)526 napi_value NapiAudioRenderer::GetRendererSamplingRate(napi_env env, napi_callback_info info)
527 {
528     auto context = std::make_shared<AudioRendererAsyncContext>();
529     if (context == nullptr) {
530         AUDIO_ERR_LOG("GetRendererSamplingRate failed : no memory");
531         NapiAudioError::ThrowError(env, "GetRendererSamplingRate failed : no memory",
532             NAPI_ERR_NO_MEMORY);
533         return NapiParamUtils::GetUndefinedValue(env);
534     }
535 
536     context->GetCbInfo(env, info);
537 
538     auto executor = [context]() {
539         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
540         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
541         ObjectRefMap objectGuard(obj);
542         auto *napiAudioRenderer = objectGuard.GetPtr();
543         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
544             "context object state is error.");
545         context->rendererSampleRate = napiAudioRenderer->audioRenderer_->GetRendererSamplingRate();
546     };
547 
548     auto complete = [env, context](napi_value &output) {
549         NapiParamUtils::SetValueUInt32(env, context->rendererSampleRate, output);
550     };
551     return NapiAsyncWork::Enqueue(env, context, "GetRendererSamplingRate", executor, complete);
552 }
553 
Start(napi_env env,napi_callback_info info)554 napi_value NapiAudioRenderer::Start(napi_env env, napi_callback_info info)
555 {
556     auto context = std::make_shared<AudioRendererAsyncContext>();
557     if (context == nullptr) {
558         AUDIO_ERR_LOG("Start failed : no memory");
559         NapiAudioError::ThrowError(env, "Start failed : no memory", NAPI_ERR_NO_MEMORY);
560         return NapiParamUtils::GetUndefinedValue(env);
561     }
562 
563     context->GetCbInfo(env, info);
564 #ifdef FEATURE_HIVIEW_ENABLE
565 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
566     HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Audio");
567 #endif
568 #endif
569 
570     auto executor = [context]() {
571         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
572         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
573         ObjectRefMap objectGuard(obj);
574         auto *napiAudioRenderer = objectGuard.GetPtr();
575         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
576             "context object state is error.");
577         context->isTrue = napiAudioRenderer->audioRenderer_->Start();
578         context->status = context->isTrue ? napi_ok : napi_generic_failure;
579         if (context->status != napi_ok) {
580             context->SignError(NAPI_ERR_SYSTEM);
581         }
582     };
583 
584     auto complete = [env](napi_value &output) {
585         output = NapiParamUtils::GetUndefinedValue(env);
586     };
587     return NapiAsyncWork::Enqueue(env, context, "Start", executor, complete);
588 }
589 
Write(napi_env env,napi_callback_info info)590 napi_value NapiAudioRenderer::Write(napi_env env, napi_callback_info info)
591 {
592     auto context = std::make_shared<AudioRendererAsyncContext>();
593     if (context == nullptr) {
594         AUDIO_ERR_LOG("Write failed : no memory");
595         NapiAudioError::ThrowError(env, "Write failed : no memory", NAPI_ERR_NO_MEMORY);
596         return NapiParamUtils::GetUndefinedValue(env);
597     }
598 
599     auto inputParser = [env, context](size_t argc, napi_value *argv) {
600         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
601             NAPI_ERR_INVALID_PARAM);
602         context->status = NapiParamUtils::GetArrayBuffer(env, context->data, context->bufferLen, argv[PARAM0]);
603         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get buffer failed",
604             NAPI_ERR_INVALID_PARAM);
605     };
606 
607     context->GetCbInfo(env, info, inputParser);
608 
609     auto executor = [context]() {
610         context->status = WriteArrayBufferToNative(context);
611         if (context->status != napi_ok) {
612             context->SignError(NAPI_ERR_SYSTEM);
613         }
614     };
615 
616     auto complete = [env, context](napi_value &output) {
617         NapiParamUtils::SetValueUInt32(env, context->totalBytesWritten, output);
618     };
619     return NapiAsyncWork::Enqueue(env, context, "Write", executor, complete);
620 }
621 
WriteArrayBufferToNative(std::shared_ptr<AudioRendererAsyncContext> context)622 napi_status NapiAudioRenderer::WriteArrayBufferToNative(std::shared_ptr<AudioRendererAsyncContext> context)
623 {
624     CHECK_AND_RETURN_RET_LOG(CheckContextStatus(context), napi_generic_failure, "context object state is error.");
625     auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
626     ObjectRefMap objectGuard(obj);
627     auto *napiAudioRenderer = objectGuard.GetPtr();
628     CHECK_AND_RETURN_RET_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
629         napi_generic_failure, "context object state is error.");
630     size_t bufferLen = context->bufferLen;
631     context->status = napi_generic_failure;
632     auto buffer = std::make_unique<uint8_t[]>(bufferLen);
633     CHECK_AND_RETURN_RET_LOG(buffer != nullptr, napi_generic_failure, "Renderer write buffer allocation failed");
634     if (memcpy_s(buffer.get(), bufferLen, context->data, bufferLen)) {
635         AUDIO_ERR_LOG("Renderer mem copy failed");
636         return napi_generic_failure;
637     }
638     int32_t bytesWritten = 0;
639     size_t totalBytesWritten = 0;
640     size_t minBytes = 4;
641     while ((totalBytesWritten < bufferLen) && ((bufferLen - totalBytesWritten) > minBytes)) {
642         bytesWritten = napiAudioRenderer->audioRenderer_->Write(buffer.get() + totalBytesWritten,
643         bufferLen - totalBytesWritten);
644         if (bytesWritten < 0) {
645             AUDIO_ERR_LOG("Write length < 0,break.");
646             break;
647         }
648         totalBytesWritten += static_cast<size_t>(bytesWritten);
649     }
650     context->status = napi_ok;
651     context->totalBytesWritten = totalBytesWritten;
652     return context->status;
653 }
654 
GetAudioTime(napi_env env,napi_callback_info info)655 napi_value NapiAudioRenderer::GetAudioTime(napi_env env, napi_callback_info info)
656 {
657     auto context = std::make_shared<AudioRendererAsyncContext>();
658     if (context == nullptr) {
659         AUDIO_ERR_LOG("GetAudioTime failed : no memory");
660         NapiAudioError::ThrowError(env, "GetAudioTime failed : no memory", NAPI_ERR_NO_MEMORY);
661         return NapiParamUtils::GetUndefinedValue(env);
662     }
663 
664     context->GetCbInfo(env, info);
665 
666     auto executor = [context]() {
667         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
668         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
669         ObjectRefMap objectGuard(obj);
670         auto *napiAudioRenderer = objectGuard.GetPtr();
671         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
672             "context object state is error.");
673         Timestamp timestamp;
674         if (napiAudioRenderer->audioRenderer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC)) {
675             const uint64_t secToNanosecond = 1000000000;
676             context->time = static_cast<uint64_t>(timestamp.time.tv_nsec) +
677                 static_cast<uint64_t>(timestamp.time.tv_sec) * secToNanosecond;
678             context->status = napi_ok;
679         } else {
680             context->SignError(NAPI_ERR_SYSTEM);
681         }
682     };
683 
684     auto complete = [env, context](napi_value &output) {
685         NapiParamUtils::SetValueInt64(env, context->time, output);
686     };
687     return NapiAsyncWork::Enqueue(env, context, "GetAudioTime", executor, complete);
688 }
689 
GetAudioTimeSync(napi_env env,napi_callback_info info)690 napi_value NapiAudioRenderer::GetAudioTimeSync(napi_env env, napi_callback_info info)
691 {
692     napi_value result = nullptr;
693     size_t argc = PARAM0;
694     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
695     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
696         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
697 
698     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
699     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
700     Timestamp timestamp;
701     bool ret = napiAudioRenderer->audioRenderer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC);
702     CHECK_AND_RETURN_RET_LOG(ret, result, "GetAudioTime failure!");
703 
704     const uint64_t secToNanosecond = 1000000000;
705     uint64_t time = static_cast<uint64_t>(timestamp.time.tv_nsec) +
706         static_cast<uint64_t>(timestamp.time.tv_sec) * secToNanosecond;
707 
708     NapiParamUtils::SetValueInt64(env, time, result);
709     return result;
710 }
711 
GetAudioTimestampInfo(napi_env env,napi_callback_info info)712 napi_value NapiAudioRenderer::GetAudioTimestampInfo(napi_env env, napi_callback_info info)
713 {
714     auto context = std::make_shared<AudioRendererAsyncContext>();
715     if (context == nullptr) {
716         AUDIO_ERR_LOG("GetAudioTimestampInfo failed : no memory");
717         NapiAudioError::ThrowError(env, "GetAudioTimestampInfo failed : no memory", NAPI_ERR_NO_MEMORY);
718         return NapiParamUtils::GetUndefinedValue(env);
719     }
720 
721     context->GetCbInfo(env, info);
722 
723     auto executor = [context]() {
724         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
725         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
726         ObjectRefMap objectGuard(obj);
727         auto *napiAudioRenderer = objectGuard.GetPtr();
728         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
729             "context object state is error.");
730         int32_t ret = napiAudioRenderer->audioRenderer_->GetAudioTimestampInfo(context->timeStamp,
731             Timestamp::Timestampbase::MONOTONIC);
732         if (ret != SUCCESS) {
733             context->SignError(NAPI_ERR_SYSTEM);
734         }
735     };
736 
737     auto complete = [env, context](napi_value &output) {
738         NapiParamUtils::SetTimeStampInfo(env, context->timeStamp, output);
739     };
740 
741     return NapiAsyncWork::Enqueue(env, context, "GetAudioTimestampInfo", executor, complete);
742 }
743 
GetAudioTimestampInfoSync(napi_env env,napi_callback_info info)744 napi_value NapiAudioRenderer::GetAudioTimestampInfoSync(napi_env env, napi_callback_info info)
745 {
746     napi_value result = nullptr;
747     size_t argc = PARAM0;
748     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
749     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
750         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
751 
752     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
753     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
754 
755     Timestamp timeStamp;
756     int32_t ret = napiAudioRenderer->audioRenderer_->GetAudioTimestampInfo(timeStamp,
757         Timestamp::Timestampbase::MONOTONIC);
758     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetAudioTimeStamp failure!");
759 
760     NapiParamUtils::SetTimeStampInfo(env, timeStamp, result);
761     return result;
762 }
763 
Drain(napi_env env,napi_callback_info info)764 napi_value NapiAudioRenderer::Drain(napi_env env, napi_callback_info info)
765 {
766     auto context = std::make_shared<AudioRendererAsyncContext>();
767     if (context == nullptr) {
768         AUDIO_ERR_LOG("Drain failed : no memory");
769         NapiAudioError::ThrowError(env, "Drain failed : no memory", NAPI_ERR_NO_MEMORY);
770         return NapiParamUtils::GetUndefinedValue(env);
771     }
772 
773     context->GetCbInfo(env, info);
774 
775     auto executor = [context]() {
776         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
777         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
778         ObjectRefMap objectGuard(obj);
779         auto *napiAudioRenderer = objectGuard.GetPtr();
780         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
781             "context object state is error.");
782         context->isTrue = napiAudioRenderer->audioRenderer_->Drain();
783         if (!context->isTrue) {
784             context->SignError(NAPI_ERR_SYSTEM);
785         }
786     };
787     auto complete = [env](napi_value &output) {
788         output = NapiParamUtils::GetUndefinedValue(env);
789     };
790     return NapiAsyncWork::Enqueue(env, context, "Drain", executor, complete);
791 }
792 
Flush(napi_env env,napi_callback_info info)793 napi_value NapiAudioRenderer::Flush(napi_env env, napi_callback_info info)
794 {
795     auto context = std::make_shared<AudioRendererAsyncContext>();
796     if (context == nullptr) {
797         AUDIO_ERR_LOG("Flush failed : no memory");
798         NapiAudioError::ThrowError(env, "Flush failed : no memory", NAPI_ERR_NO_MEMORY);
799         return NapiParamUtils::GetUndefinedValue(env);
800     }
801 
802     context->GetCbInfo(env, info, nullptr, true);
803 
804     auto executor = [context]() {
805         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
806         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
807         ObjectRefMap objectGuard(obj);
808         auto *napiAudioRenderer = objectGuard.GetPtr();
809         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
810             "context object state is error.");
811         context->isTrue = napiAudioRenderer->audioRenderer_->Flush();
812         if (!context->isTrue) {
813             context->SignError(NAPI_ERR_ILLEGAL_STATE);
814         }
815     };
816     auto complete = [env](napi_value &output) {
817         output = NapiParamUtils::GetUndefinedValue(env);
818     };
819     return NapiAsyncWork::Enqueue(env, context, "Flush", executor, complete);
820 }
821 
Pause(napi_env env,napi_callback_info info)822 napi_value NapiAudioRenderer::Pause(napi_env env, napi_callback_info info)
823 {
824     auto context = std::make_shared<AudioRendererAsyncContext>();
825     if (context == nullptr) {
826         AUDIO_ERR_LOG("Pause failed : no memory");
827         NapiAudioError::ThrowError(env, "Pause failed : no memory", NAPI_ERR_NO_MEMORY);
828         return NapiParamUtils::GetUndefinedValue(env);
829     }
830 
831     context->GetCbInfo(env, info);
832 
833     auto executor = [context]() {
834         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
835         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
836         ObjectRefMap objectGuard(obj);
837         auto *napiAudioRenderer = objectGuard.GetPtr();
838         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
839             "context object state is error.");
840         context->isTrue = napiAudioRenderer->audioRenderer_->Pause();
841         if (!context->isTrue) {
842             context->SignError(NAPI_ERR_SYSTEM);
843         }
844     };
845     auto complete = [env](napi_value &output) {
846         output = NapiParamUtils::GetUndefinedValue(env);
847     };
848     return NapiAsyncWork::Enqueue(env, context, "Pause", executor, complete);
849 }
850 
Stop(napi_env env,napi_callback_info info)851 napi_value NapiAudioRenderer::Stop(napi_env env, napi_callback_info info)
852 {
853     auto context = std::make_shared<AudioRendererAsyncContext>();
854     if (context == nullptr) {
855         AUDIO_ERR_LOG("Stop failed : no memory");
856         NapiAudioError::ThrowError(env, "Stop failed : no memory", NAPI_ERR_NO_MEMORY);
857         return NapiParamUtils::GetUndefinedValue(env);
858     }
859 
860     context->GetCbInfo(env, info);
861 
862     auto executor = [context]() {
863         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
864         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
865         ObjectRefMap objectGuard(obj);
866         auto *napiAudioRenderer = objectGuard.GetPtr();
867         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
868             "context object state is error.");
869         context->isTrue = napiAudioRenderer->audioRenderer_->Stop();
870         if (!context->isTrue) {
871             context->SignError(NAPI_ERR_SYSTEM);
872         }
873     };
874     auto complete = [env](napi_value &output) {
875         output = NapiParamUtils::GetUndefinedValue(env);
876     };
877     return NapiAsyncWork::Enqueue(env, context, "Stop", executor, complete);
878 }
879 
Release(napi_env env,napi_callback_info info)880 napi_value NapiAudioRenderer::Release(napi_env env, napi_callback_info info)
881 {
882     auto context = std::make_shared<AudioRendererAsyncContext>();
883     if (context == nullptr) {
884         AUDIO_ERR_LOG("Release failed : no memory");
885         NapiAudioError::ThrowError(env, "Release failed : no memory", NAPI_ERR_NO_MEMORY);
886         return NapiParamUtils::GetUndefinedValue(env);
887     }
888 
889     context->GetCbInfo(env, info);
890 
891     auto executor = [context]() {
892         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
893         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
894         ObjectRefMap objectGuard(obj);
895         auto *napiAudioRenderer = objectGuard.GetPtr();
896         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
897             "context object state is error.");
898         context->isTrue = napiAudioRenderer->audioRenderer_->Release();
899         if (!context->isTrue) {
900             context->SignError(NAPI_ERR_SYSTEM);
901         }
902     };
903     auto complete = [env](napi_value &output) {
904         output = NapiParamUtils::GetUndefinedValue(env);
905     };
906     return NapiAsyncWork::Enqueue(env, context, "Release", executor, complete);
907 }
908 
GetBufferSize(napi_env env,napi_callback_info info)909 napi_value NapiAudioRenderer::GetBufferSize(napi_env env, napi_callback_info info)
910 {
911     auto context = std::make_shared<AudioRendererAsyncContext>();
912     if (context == nullptr) {
913         AUDIO_ERR_LOG("GetBufferSize failed : no memory");
914         NapiAudioError::ThrowError(env, "GetBufferSize failed : no memory", NAPI_ERR_NO_MEMORY);
915         return NapiParamUtils::GetUndefinedValue(env);
916     }
917 
918     context->GetCbInfo(env, info);
919 
920     auto executor = [context]() {
921         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
922         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
923         ObjectRefMap objectGuard(obj);
924         auto *napiAudioRenderer = objectGuard.GetPtr();
925         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
926             "context object state is error.");
927         size_t bufferSize;
928         context->intValue = napiAudioRenderer->audioRenderer_->GetBufferSize(bufferSize);
929         if (context->intValue != SUCCESS) {
930             context->SignError(NAPI_ERR_SYSTEM);
931         } else {
932             context->bufferSize = bufferSize;
933         }
934     };
935     auto complete = [env, context](napi_value &output) {
936         NapiParamUtils::SetValueUInt32(env, context->bufferSize, output);
937     };
938     return NapiAsyncWork::Enqueue(env, context, "GetBufferSize", executor, complete);
939 }
940 
GetBufferSizeSync(napi_env env,napi_callback_info info)941 napi_value NapiAudioRenderer::GetBufferSizeSync(napi_env env, napi_callback_info info)
942 {
943     napi_value result = nullptr;
944     size_t argc = PARAM0;
945     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
946     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
947         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
948 
949     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
950     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
951     size_t bufferSize;
952     int32_t ret = napiAudioRenderer->audioRenderer_->GetBufferSize(bufferSize);
953     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetBufferSize failure!");
954 
955     NapiParamUtils::SetValueUInt32(env, bufferSize, result);
956     return result;
957 }
958 
GetAudioStreamId(napi_env env,napi_callback_info info)959 napi_value NapiAudioRenderer::GetAudioStreamId(napi_env env, napi_callback_info info)
960 {
961     auto context = std::make_shared<AudioRendererAsyncContext>();
962     if (context == nullptr) {
963         AUDIO_ERR_LOG("GetAudioStreamId failed : no memory");
964         NapiAudioError::ThrowError(env, "GetAudioStreamId failed : no memory", NAPI_ERR_NO_MEMORY);
965         return NapiParamUtils::GetUndefinedValue(env);
966     }
967 
968     context->GetCbInfo(env, info);
969 
970     auto executor = [context]() {
971         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
972         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
973         ObjectRefMap objectGuard(obj);
974         auto *napiAudioRenderer = objectGuard.GetPtr();
975         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
976             "context object state is error.");
977         context->intValue = napiAudioRenderer->audioRenderer_->GetAudioStreamId(context->audioStreamId);
978         if (context->intValue == ERR_INVALID_INDEX) {
979             context->SignError(NAPI_ERR_SYSTEM);
980         } else if (context->intValue == ERR_ILLEGAL_STATE) {
981             context->SignError(NAPI_ERR_ILLEGAL_STATE);
982         }
983     };
984     auto complete = [env, context](napi_value &output) {
985         NapiParamUtils::SetValueUInt32(env, context->audioStreamId, output);
986     };
987     return NapiAsyncWork::Enqueue(env, context, "GetAudioStreamId", executor, complete);
988 }
989 
GetAudioStreamIdSync(napi_env env,napi_callback_info info)990 napi_value NapiAudioRenderer::GetAudioStreamIdSync(napi_env env, napi_callback_info info)
991 {
992     napi_value result = nullptr;
993     size_t argc = PARAM0;
994     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
995     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
996         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
997 
998     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
999     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1000     uint32_t audioStreamId;
1001     int32_t streamIdStatus = napiAudioRenderer->audioRenderer_->GetAudioStreamId(audioStreamId);
1002     CHECK_AND_RETURN_RET_LOG(streamIdStatus == SUCCESS, result, "GetAudioStreamId failure!");
1003 
1004     NapiParamUtils::SetValueUInt32(env, audioStreamId, result);
1005     return result;
1006 }
1007 
SetVolume(napi_env env,napi_callback_info info)1008 napi_value NapiAudioRenderer::SetVolume(napi_env env, napi_callback_info info)
1009 {
1010     auto context = std::make_shared<AudioRendererAsyncContext>();
1011     if (context == nullptr) {
1012         AUDIO_ERR_LOG("SetVolume failed : no memory");
1013         NapiAudioError::ThrowError(env, "SetVolume failed : no memory", NAPI_ERR_NO_MEMORY);
1014         return NapiParamUtils::GetUndefinedValue(env);
1015     }
1016 
1017     auto inputParser = [env, context](size_t argc, napi_value *argv) {
1018         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
1019             NAPI_ERR_INVALID_PARAM);
1020         context->status = NapiParamUtils::GetValueDouble(env, context->volLevel, argv[PARAM0]);
1021         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get RendererSamplingRate failed",
1022             NAPI_ERR_INVALID_PARAM);
1023     };
1024 
1025     context->GetCbInfo(env, info, inputParser);
1026 
1027     auto executor = [context]() {
1028         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1029         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1030         ObjectRefMap objectGuard(obj);
1031         auto *napiAudioRenderer = objectGuard.GetPtr();
1032         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1033             "context object state is error.");
1034         if (context->volLevel < MIN_VOLUME_IN_DOUBLE || context->volLevel > MAX_VOLUME_IN_DOUBLE) {
1035             context->SignError(NAPI_ERR_UNSUPPORTED);
1036             return;
1037         }
1038         context->intValue = napiAudioRenderer->audioRenderer_->SetVolume(static_cast<float>(context->volLevel));
1039         if (context->intValue != SUCCESS) {
1040             context->SignError(NAPI_ERR_SYSTEM);
1041         }
1042     };
1043 
1044     auto complete = [env](napi_value &output) {
1045         output = NapiParamUtils::GetUndefinedValue(env);
1046     };
1047     return NapiAsyncWork::Enqueue(env, context, "SetVolume", executor, complete);
1048 }
1049 
GetVolume(napi_env env,napi_callback_info info)1050 napi_value NapiAudioRenderer::GetVolume(napi_env env, napi_callback_info info)
1051 {
1052     napi_value result = nullptr;
1053     size_t argc = PARAM0;
1054     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1055     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1056     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1057 
1058     double volLevel = napiAudioRenderer->audioRenderer_->GetVolume();
1059     NapiParamUtils::SetValueDouble(env, volLevel, result);
1060     return result;
1061 }
1062 
SetLoudnessGain(napi_env env,napi_callback_info info)1063 napi_value NapiAudioRenderer::SetLoudnessGain(napi_env env, napi_callback_info info)
1064 {
1065     auto context = std::make_shared<AudioRendererAsyncContext>();
1066     if (context == nullptr) {
1067         AUDIO_ERR_LOG("SetLoudnessGain failed : no memory");
1068         NapiAudioError::ThrowError(env, "SetLoudnessGain failed : no memory", NAPI_ERR_NO_MEMORY);
1069         return NapiParamUtils::GetUndefinedValue(env);
1070     }
1071 
1072     auto inputParser = [env, context](size_t argc, napi_value *argv) {
1073         NAPI_CHECK_ARGS_RETURN_VOID(context, argc == ARGS_ONE, "set loudnessGain failed, invalid arguments",
1074             NAPI_ERR_INPUT_INVALID);
1075         context->status = NapiParamUtils::GetValueDouble(env, context->loudnessGain, argv[PARAM0]);
1076         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "set loudnessGain failed, invalid param type",
1077             NAPI_ERR_INPUT_INVALID);
1078     };
1079 
1080     context->GetCbInfo(env, info, inputParser);
1081 
1082     auto executor = [context]() {
1083         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1084         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1085         ObjectRefMap objectGuard(obj);
1086         auto *napiAudioRenderer = objectGuard.GetPtr();
1087         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1088             "context object state is error.");
1089         AudioRendererInfo rendererInfo = {};
1090         napiAudioRenderer->audioRenderer_->GetRendererInfo(rendererInfo);
1091         StreamUsage streamUsage = rendererInfo.streamUsage;
1092         if (streamUsage != STREAM_USAGE_MUSIC && streamUsage != STREAM_USAGE_MOVIE &&
1093             streamUsage != STREAM_USAGE_AUDIOBOOK) {
1094             context->SignError(NAPI_ERR_UNSUPPORTED);
1095             return;
1096         }
1097         if (context->loudnessGain < MIN_LOUDNESS_GAIN_IN_DOUBLE ||
1098             context->loudnessGain > MAX_LOUDNESS_GAIN_IN_DOUBLE) {
1099             context->SignError(NAPI_ERROR_INVALID_PARAM);
1100             return;
1101         }
1102         context->intValue = napiAudioRenderer->audioRenderer_->
1103             SetLoudnessGain(static_cast<float>(context->loudnessGain));
1104         if (context->intValue == ERR_PRO_STREAM_NOT_SUPPORTED) {
1105             context->SignError(NAPI_ERR_UNSUPPORTED);
1106             return;
1107         }
1108         if (context->intValue != SUCCESS) {
1109             context->SignError(NAPI_ERR_SYSTEM);
1110         }
1111     };
1112 
1113     auto complete = [env](napi_value &output) {
1114         output = NapiParamUtils::GetUndefinedValue(env);
1115     };
1116     return NapiAsyncWork::Enqueue(env, context, "SetLoudnessGain", executor, complete);
1117 }
1118 
GetLoudnessGain(napi_env env,napi_callback_info info)1119 napi_value NapiAudioRenderer::GetLoudnessGain(napi_env env, napi_callback_info info)
1120 {
1121     napi_value result = nullptr;
1122     size_t argc = PARAM0;
1123     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1124     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1125     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1126 
1127     double loudnessGain = napiAudioRenderer->audioRenderer_->GetLoudnessGain();
1128     NapiParamUtils::SetValueDouble(env, loudnessGain, result);
1129     return result;
1130 }
1131 
GetRendererInfo(napi_env env,napi_callback_info info)1132 napi_value NapiAudioRenderer::GetRendererInfo(napi_env env, napi_callback_info info)
1133 {
1134     auto context = std::make_shared<AudioRendererAsyncContext>();
1135     if (context == nullptr) {
1136         AUDIO_ERR_LOG("GetRendererInfo failed : no memory");
1137         NapiAudioError::ThrowError(env, "GetRendererInfo failed : no memory", NAPI_ERR_NO_MEMORY);
1138         return NapiParamUtils::GetUndefinedValue(env);
1139     }
1140 
1141     context->GetCbInfo(env, info);
1142 
1143     auto executor = [context]() {
1144         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1145         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1146         ObjectRefMap objectGuard(obj);
1147         auto *napiAudioRenderer = objectGuard.GetPtr();
1148         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1149             "context object state is error.");
1150         context->intValue = napiAudioRenderer->audioRenderer_->GetRendererInfo(context->rendererInfo);
1151         if (context->intValue != SUCCESS) {
1152             context->SignError(NAPI_ERR_SYSTEM);
1153         }
1154     };
1155 
1156     auto complete = [env, context](napi_value &output) {
1157         NapiParamUtils::SetRendererInfo(env, context->rendererInfo, output);
1158     };
1159     return NapiAsyncWork::Enqueue(env, context, "GetRendererInfo", executor, complete);
1160 }
1161 
GetRendererInfoSync(napi_env env,napi_callback_info info)1162 napi_value NapiAudioRenderer::GetRendererInfoSync(napi_env env, napi_callback_info info)
1163 {
1164     napi_value result = nullptr;
1165     size_t argc = PARAM0;
1166     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1167     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
1168         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
1169 
1170     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1171     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1172     AudioRendererInfo rendererInfo = {};
1173     int32_t ret = napiAudioRenderer->audioRenderer_->GetRendererInfo(rendererInfo);
1174     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetRendererInfo failure!");
1175     NapiParamUtils::SetRendererInfo(env, rendererInfo, result);
1176     return result;
1177 }
1178 
GetStreamInfo(napi_env env,napi_callback_info info)1179 napi_value NapiAudioRenderer::GetStreamInfo(napi_env env, napi_callback_info info)
1180 {
1181     auto context = std::make_shared<AudioRendererAsyncContext>();
1182     if (context == nullptr) {
1183         AUDIO_ERR_LOG("GetStreamInfo failed : no memory");
1184         NapiAudioError::ThrowError(env, "GetStreamInfo failed : no memory", NAPI_ERR_NO_MEMORY);
1185         return NapiParamUtils::GetUndefinedValue(env);
1186     }
1187 
1188     context->GetCbInfo(env, info);
1189 
1190     auto executor = [context]() {
1191         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1192         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1193         ObjectRefMap objectGuard(obj);
1194         auto *napiAudioRenderer = objectGuard.GetPtr();
1195         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1196             "context object state is error.");
1197         context->intValue = napiAudioRenderer->audioRenderer_->GetStreamInfo(context->streamInfo);
1198         if (context->intValue != SUCCESS) {
1199             context->SignError(NAPI_ERR_SYSTEM);
1200         }
1201     };
1202 
1203     auto complete = [env, context](napi_value &output) {
1204         NapiParamUtils::SetStreamInfo(env, context->streamInfo, output);
1205     };
1206     return NapiAsyncWork::Enqueue(env, context, "GetStreamInfo", executor, complete);
1207 }
1208 
GetStreamInfoSync(napi_env env,napi_callback_info info)1209 napi_value NapiAudioRenderer::GetStreamInfoSync(napi_env env, napi_callback_info info)
1210 {
1211     napi_value result = nullptr;
1212     size_t argc = PARAM0;
1213     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1214     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
1215         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
1216 
1217     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1218     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1219 
1220     AudioStreamInfo streamInfo;
1221     int32_t ret = napiAudioRenderer->audioRenderer_->GetStreamInfo(streamInfo);
1222     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetStreamInfo failure!");
1223     NapiParamUtils::SetStreamInfo(env, streamInfo, result);
1224     return result;
1225 }
1226 
SetInterruptMode(napi_env env,napi_callback_info info)1227 napi_value NapiAudioRenderer::SetInterruptMode(napi_env env, napi_callback_info info)
1228 {
1229     auto context = std::make_shared<AudioRendererAsyncContext>();
1230     if (context == nullptr) {
1231         AUDIO_ERR_LOG("SetInterruptMode failed : no memory");
1232         NapiAudioError::ThrowError(env, "SetInterruptMode failed : no memory", NAPI_ERR_NO_MEMORY);
1233         return NapiParamUtils::GetUndefinedValue(env);
1234     }
1235 
1236     auto inputParser = [env, context](size_t argc, napi_value *argv) {
1237         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
1238             NAPI_ERR_INVALID_PARAM);
1239         context->status = NapiParamUtils::GetValueInt32(env, context->interruptMode, argv[PARAM0]);
1240         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get interruptMode failed",
1241             NAPI_ERR_INVALID_PARAM);
1242     };
1243     context->GetCbInfo(env, info, inputParser);
1244 
1245     auto executor = [context]() {
1246         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1247         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1248         ObjectRefMap objectGuard(obj);
1249         auto *napiAudioRenderer = objectGuard.GetPtr();
1250         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1251             "context object state is error.");
1252         InterruptMode interruptMode = NapiAudioEnum::GetNativeInterruptMode(context->interruptMode);
1253         napiAudioRenderer->audioRenderer_->SetInterruptMode(interruptMode);
1254     };
1255 
1256     auto complete = [env](napi_value &output) {
1257         output = NapiParamUtils::GetUndefinedValue(env);
1258     };
1259     return NapiAsyncWork::Enqueue(env, context, "SetInterruptMode", executor, complete);
1260 }
1261 
SetInterruptModeSync(napi_env env,napi_callback_info info)1262 napi_value NapiAudioRenderer::SetInterruptModeSync(napi_env env, napi_callback_info info)
1263 {
1264     AUDIO_INFO_LOG("SetInterruptModeSync");
1265     napi_value result = nullptr;
1266     size_t argc = ARGS_ONE;
1267     napi_value args[ARGS_ONE] = {};
1268     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, args);
1269     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
1270         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argcCount invaild");
1271 
1272     napi_valuetype valueType = napi_undefined;
1273     napi_typeof(env, args[PARAM0], &valueType);
1274     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
1275         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of mode must be number"),
1276         "valueType invaild");
1277 
1278     int32_t interruptMode;
1279     NapiParamUtils::GetValueInt32(env, interruptMode, args[PARAM0]);
1280 
1281     if (!NapiAudioEnum::IsLegalInputArgumentInterruptMode(interruptMode)) {
1282         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1283             "parameter verification failed: The param of mode must be enum InterruptMode");
1284         return result;
1285     }
1286     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1287     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1288     napiAudioRenderer->audioRenderer_->SetInterruptMode(NapiAudioEnum::GetNativeInterruptMode(interruptMode));
1289 
1290     return result;
1291 }
1292 
GetMinStreamVolume(napi_env env,napi_callback_info info)1293 napi_value NapiAudioRenderer::GetMinStreamVolume(napi_env env, napi_callback_info info)
1294 {
1295     auto context = std::make_shared<AudioRendererAsyncContext>();
1296     if (context == nullptr) {
1297         AUDIO_ERR_LOG("GetMinStreamVolume failed : no memory");
1298         NapiAudioError::ThrowError(env, "GetMinStreamVolume failed : no memory", NAPI_ERR_NO_MEMORY);
1299         return NapiParamUtils::GetUndefinedValue(env);
1300     }
1301 
1302     context->GetCbInfo(env, info);
1303 
1304     auto executor = [context]() {
1305         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1306         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1307         ObjectRefMap objectGuard(obj);
1308         auto *napiAudioRenderer = objectGuard.GetPtr();
1309         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1310             "context object state is error.");
1311         context->volLevel = napiAudioRenderer->audioRenderer_->GetMinStreamVolume();
1312     };
1313 
1314     auto complete = [env, context](napi_value &output) {
1315         NapiParamUtils::SetValueDouble(env, context->volLevel, output);
1316     };
1317     return NapiAsyncWork::Enqueue(env, context, "GetMinStreamVolume", executor, complete);
1318 }
1319 
GetMinStreamVolumeSync(napi_env env,napi_callback_info info)1320 napi_value NapiAudioRenderer::GetMinStreamVolumeSync(napi_env env, napi_callback_info info)
1321 {
1322     napi_value result = nullptr;
1323     size_t argc = PARAM0;
1324     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1325     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
1326         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
1327 
1328     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1329     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1330 
1331     double volLevel = napiAudioRenderer->audioRenderer_->GetMinStreamVolume();
1332     NapiParamUtils::SetValueDouble(env, volLevel, result);
1333     return result;
1334 }
1335 
GetMaxStreamVolume(napi_env env,napi_callback_info info)1336 napi_value NapiAudioRenderer::GetMaxStreamVolume(napi_env env, napi_callback_info info)
1337 {
1338     auto context = std::make_shared<AudioRendererAsyncContext>();
1339     if (context == nullptr) {
1340         AUDIO_ERR_LOG("GetMaxStreamVolume failed : no memory");
1341         NapiAudioError::ThrowError(env, "GetMaxStreamVolume failed : no memory", NAPI_ERR_NO_MEMORY);
1342         return NapiParamUtils::GetUndefinedValue(env);
1343     }
1344 
1345     context->GetCbInfo(env, info);
1346 
1347     auto executor = [context]() {
1348         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1349         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1350         ObjectRefMap objectGuard(obj);
1351         auto *napiAudioRenderer = objectGuard.GetPtr();
1352         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1353             "context object state is error.");
1354         context->volLevel = napiAudioRenderer->audioRenderer_->GetMaxStreamVolume();
1355     };
1356 
1357     auto complete = [env, context](napi_value &output) {
1358         NapiParamUtils::SetValueDouble(env, context->volLevel, output);
1359     };
1360     return NapiAsyncWork::Enqueue(env, context, "GetMaxStreamVolume", executor, complete);
1361 }
1362 
GetMaxStreamVolumeSync(napi_env env,napi_callback_info info)1363 napi_value NapiAudioRenderer::GetMaxStreamVolumeSync(napi_env env, napi_callback_info info)
1364 {
1365     napi_value result = nullptr;
1366     size_t argc = PARAM0;
1367     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1368     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
1369         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
1370 
1371     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1372     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1373 
1374     double volLevel = napiAudioRenderer->audioRenderer_->GetMaxStreamVolume();
1375     NapiParamUtils::SetValueDouble(env, volLevel, result);
1376     return result;
1377 }
1378 
GetCurrentOutputDevices(napi_env env,napi_callback_info info)1379 napi_value NapiAudioRenderer::GetCurrentOutputDevices(napi_env env, napi_callback_info info)
1380 {
1381     auto context = std::make_shared<AudioRendererAsyncContext>();
1382     if (context == nullptr) {
1383         AUDIO_ERR_LOG("GetCurrentOutputDevices failed : no memory");
1384         NapiAudioError::ThrowError(env, "GetCurrentOutputDevices failed : no memory",
1385             NAPI_ERR_NO_MEMORY);
1386         return NapiParamUtils::GetUndefinedValue(env);
1387     }
1388 
1389     context->GetCbInfo(env, info);
1390 
1391     auto executor = [context]() {
1392         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1393         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1394         ObjectRefMap objectGuard(obj);
1395         auto *napiAudioRenderer = objectGuard.GetPtr();
1396         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1397             "context object state is error.");
1398         AudioDeviceDescriptor deviceInfo(AudioDeviceDescriptor::DEVICE_INFO);
1399         context->intValue = napiAudioRenderer->audioRenderer_->GetCurrentOutputDevices(deviceInfo);
1400         if (context->intValue == ERR_INVALID_PARAM) {
1401             context->SignError(NAPI_ERROR_INVALID_PARAM);
1402             return;
1403         }
1404         context->deviceInfo = deviceInfo;
1405     };
1406 
1407     auto complete = [env, context](napi_value &output) {
1408         NapiParamUtils::SetValueDeviceInfo(env, context->deviceInfo, output);
1409     };
1410     return NapiAsyncWork::Enqueue(env, context, "GetCurrentOutputDevices", executor, complete);
1411 }
1412 
GetCurrentOutputDevicesSync(napi_env env,napi_callback_info info)1413 napi_value NapiAudioRenderer::GetCurrentOutputDevicesSync(napi_env env, napi_callback_info info)
1414 {
1415     napi_value result = nullptr;
1416     size_t argc = PARAM0;
1417     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1418     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
1419         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
1420 
1421     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1422     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1423 
1424     AudioDeviceDescriptor deviceInfo(AudioDeviceDescriptor::DEVICE_INFO);
1425     int32_t ret = napiAudioRenderer->audioRenderer_->GetCurrentOutputDevices(deviceInfo);
1426     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetCurrentOutputDevices failure!");
1427 
1428     NapiParamUtils::SetValueDeviceInfo(env, deviceInfo, result);
1429     return result;
1430 }
1431 
GetUnderflowCount(napi_env env,napi_callback_info info)1432 napi_value NapiAudioRenderer::GetUnderflowCount(napi_env env, napi_callback_info info)
1433 {
1434     auto context = std::make_shared<AudioRendererAsyncContext>();
1435     if (context == nullptr) {
1436         AUDIO_ERR_LOG("GetUnderflowCount failed : no memory");
1437         NapiAudioError::ThrowError(env, "GetUnderflowCount failed : no memory", NAPI_ERR_NO_MEMORY);
1438         return NapiParamUtils::GetUndefinedValue(env);
1439     }
1440 
1441     context->GetCbInfo(env, info);
1442 
1443     auto executor = [context]() {
1444         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1445         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1446         ObjectRefMap objectGuard(obj);
1447         auto *napiAudioRenderer = objectGuard.GetPtr();
1448         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1449             "context object state is error.");
1450         context->underflowCount = napiAudioRenderer->audioRenderer_->GetUnderflowCount();
1451     };
1452 
1453     auto complete = [env, context](napi_value &output) {
1454         NapiParamUtils::SetValueUInt32(env, context->underflowCount, output);
1455     };
1456     return NapiAsyncWork::Enqueue(env, context, "GetUnderflowCount", executor, complete);
1457 }
1458 
GetUnderflowCountSync(napi_env env,napi_callback_info info)1459 napi_value NapiAudioRenderer::GetUnderflowCountSync(napi_env env, napi_callback_info info)
1460 {
1461     napi_value result = nullptr;
1462     size_t argc = PARAM0;
1463     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1464     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
1465         NAPI_ERR_INPUT_INVALID), "argcCount invaild");
1466 
1467     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1468     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1469 
1470     uint32_t underflowCount = napiAudioRenderer->audioRenderer_->GetUnderflowCount();
1471     NapiParamUtils::SetValueUInt32(env, underflowCount, result);
1472     return result;
1473 }
1474 
GetAudioEffectMode(napi_env env,napi_callback_info info)1475 napi_value NapiAudioRenderer::GetAudioEffectMode(napi_env env, napi_callback_info info)
1476 {
1477     auto context = std::make_shared<AudioRendererAsyncContext>();
1478     if (context == nullptr) {
1479         NapiAudioError::ThrowError(env, "GetAudioEffectMode failed : no memory", NAPI_ERR_NO_MEMORY);
1480         return NapiParamUtils::GetUndefinedValue(env);
1481     }
1482 
1483     context->GetCbInfo(env, info);
1484 
1485     auto executor = [context]() {
1486         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1487         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1488         ObjectRefMap objectGuard(obj);
1489         auto *napiAudioRenderer = objectGuard.GetPtr();
1490         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1491             "context object state is error.");
1492         context->intValue = napiAudioRenderer->audioRenderer_->GetAudioEffectMode();
1493     };
1494 
1495     auto complete = [env, context](napi_value &output) {
1496         NapiParamUtils::SetValueInt32(env, context->intValue, output);
1497     };
1498     return NapiAsyncWork::Enqueue(env, context, "GetAudioEffectMode", executor, complete);
1499 }
1500 
SetAudioEffectMode(napi_env env,napi_callback_info info)1501 napi_value NapiAudioRenderer::SetAudioEffectMode(napi_env env, napi_callback_info info)
1502 {
1503     auto context = std::make_shared<AudioRendererAsyncContext>();
1504     if (context == nullptr) {
1505         NapiAudioError::ThrowError(env, "SetAudioEffectMode failed : no memory", NAPI_ERR_NO_MEMORY);
1506         return NapiParamUtils::GetUndefinedValue(env);
1507     }
1508 
1509     auto inputParser = [env, context](size_t argc, napi_value *argv) {
1510         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
1511             NAPI_ERR_INPUT_INVALID);
1512         context->status = NapiParamUtils::GetValueInt32(env, context->audioEffectMode, argv[PARAM0]);
1513         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
1514             "incorrect parameter types: The type of mode must be number", NAPI_ERR_INPUT_INVALID);
1515         NAPI_CHECK_ARGS_RETURN_VOID(context,
1516             NapiAudioEnum::IsLegalInputArgumentAudioEffectMode(context->audioEffectMode),
1517             "parameter verification failed: The param of mode must be enum AudioEffectMode",
1518             NAPI_ERR_INVALID_PARAM);
1519     };
1520     context->GetCbInfo(env, info, inputParser);
1521 
1522     if ((context->status != napi_ok) && (context->errCode == NAPI_ERR_INPUT_INVALID)) {
1523         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
1524         return NapiParamUtils::GetUndefinedValue(env);
1525     }
1526 
1527     auto executor = [context]() {
1528         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1529         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1530         ObjectRefMap objectGuard(obj);
1531         auto *napiAudioRenderer = objectGuard.GetPtr();
1532         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1533             "context object state is error.");
1534         AudioEffectMode audioEffectMode = static_cast<AudioEffectMode>(context->audioEffectMode);
1535         context->intValue = napiAudioRenderer->audioRenderer_->SetAudioEffectMode(audioEffectMode);
1536         if (context->intValue != SUCCESS) {
1537             context->SignError(NAPI_ERR_SYSTEM);
1538         }
1539     };
1540 
1541     auto complete = [env](napi_value &output) {
1542         output = NapiParamUtils::GetUndefinedValue(env);
1543     };
1544     return NapiAsyncWork::Enqueue(env, context, "SetAudioEffectMode", executor, complete);
1545 }
1546 
SetChannelBlendMode(napi_env env,napi_callback_info info)1547 napi_value NapiAudioRenderer::SetChannelBlendMode(napi_env env, napi_callback_info info)
1548 {
1549     napi_value result = nullptr;
1550     size_t argc = ARGS_ONE;
1551     napi_value argv[ARGS_ONE] = {};
1552     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, argv);
1553     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
1554         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argcCount invaild");
1555 
1556     napi_valuetype valueType = napi_undefined;
1557     napi_typeof(env, argv[PARAM0], &valueType);
1558     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
1559         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of mode must be number"),
1560         "valueType params");
1561 
1562     int32_t channelBlendMode;
1563     NapiParamUtils::GetValueInt32(env, channelBlendMode, argv[PARAM0]);
1564     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentChannelBlendMode(channelBlendMode),
1565         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
1566         "parameter verification failed: The param of mode must be enum ChannelBlendMode"), "unsupport params");
1567 
1568     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer!= nullptr, result, "napiAudioRenderer is nullptr");
1569     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1570     int32_t ret =
1571         napiAudioRenderer->audioRenderer_->SetChannelBlendMode(static_cast<ChannelBlendMode>(channelBlendMode));
1572     CHECK_AND_RETURN_RET_LOG(ret != ERR_ILLEGAL_STATE,
1573         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_ILLEGAL_STATE), "err illegal state");
1574 
1575     return result;
1576 }
1577 
SetVolumeWithRamp(napi_env env,napi_callback_info info)1578 napi_value NapiAudioRenderer::SetVolumeWithRamp(napi_env env, napi_callback_info info)
1579 {
1580     AUDIO_INFO_LOG("SetVolumeWithRamp");
1581     napi_value result = nullptr;
1582     size_t argc = ARGS_TWO;
1583     napi_value argv[ARGS_TWO] = {};
1584     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, argv);
1585     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_TWO, NapiAudioError::ThrowErrorAndReturn(env,
1586         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argcCount invaild");
1587 
1588     napi_valuetype valueType = napi_undefined;
1589     napi_typeof(env, argv[PARAM0], &valueType);
1590     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
1591         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of volume must be number"),
1592         "valueType param0 invaild");
1593     napi_typeof(env, argv[PARAM1], &valueType);
1594     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
1595         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of duration must be number"),
1596         "valueType param1 invaild");
1597 
1598     double volume;
1599     NapiParamUtils::GetValueDouble(env, volume, argv[PARAM0]);
1600     CHECK_AND_RETURN_RET_LOG((volume >= MIN_VOLUME_IN_DOUBLE) && (volume <= MAX_VOLUME_IN_DOUBLE),
1601         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
1602         "Parameter verification failed. Volume param should be in range 0.0-1.0."), "invaild volume index");
1603 
1604     int32_t duration;
1605     NapiParamUtils::GetValueInt32(env, duration, argv[PARAM1]);
1606     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer!= nullptr, result, "napiAudioRenderer is nullptr");
1607     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1608     int32_t ret =
1609         napiAudioRenderer->audioRenderer_->SetVolumeWithRamp(static_cast<float>(volume), duration);
1610     CHECK_AND_RETURN_RET_LOG(ret != ERR_ILLEGAL_STATE,
1611         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_ILLEGAL_STATE), "err illegal state");
1612     return result;
1613 }
1614 
SetSpeed(napi_env env,napi_callback_info info)1615 napi_value NapiAudioRenderer::SetSpeed(napi_env env, napi_callback_info info)
1616 {
1617     AUDIO_INFO_LOG("SetSpeed");
1618     napi_value result = nullptr;
1619     size_t argc = ARGS_ONE;
1620     napi_value argv[ARGS_ONE] = {};
1621     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, argv);
1622     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
1623         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argcCount invaild");
1624 
1625     napi_valuetype valueType = napi_undefined;
1626     napi_typeof(env, argv[PARAM0], &valueType);
1627     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
1628         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of speed must be number"),
1629         "valueType param0 invaild");
1630 
1631     double speed;
1632     NapiParamUtils::GetValueDouble(env, speed, argv[PARAM0]);
1633     CHECK_AND_RETURN_RET_LOG((speed >= MIN_STREAM_SPEED_LEVEL) && (speed <= MAX_STREAM_SPEED_LEVEL),
1634         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM),
1635         "parameter verification failed: invaild speed index");
1636 
1637     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer!= nullptr, result, "napiAudioRenderer is nullptr");
1638     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1639     int32_t ret = napiAudioRenderer->audioRenderer_->SetSpeed(static_cast<float>(speed));
1640     CHECK_AND_RETURN_RET_LOG(ret != ERR_ILLEGAL_STATE,
1641         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_ILLEGAL_STATE), "err illegal state");
1642     return result;
1643 }
1644 
GetSpeed(napi_env env,napi_callback_info info)1645 napi_value NapiAudioRenderer::GetSpeed(napi_env env, napi_callback_info info)
1646 {
1647     AUDIO_INFO_LOG("GetSpeed");
1648     napi_value result = nullptr;
1649     size_t argc = ARGS_ONE;
1650     napi_value argv[ARGS_ONE] = {};
1651     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, argv);
1652     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer!= nullptr, result, "napiAudioRenderer is nullptr");
1653     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1654 
1655     double ret = napiAudioRenderer->audioRenderer_->GetSpeed();
1656     napi_create_double(env, ret, &result);
1657     return result;
1658 }
1659 
GetState(napi_env env,napi_callback_info info)1660 napi_value NapiAudioRenderer::GetState(napi_env env, napi_callback_info info)
1661 {
1662     napi_value result = nullptr;
1663     size_t argc = PARAM0;
1664     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, nullptr);
1665     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
1666         NAPI_ERR_INPUT_INVALID), "invaild params");
1667 
1668     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer!= nullptr, result, "napiAudioRenderer is nullptr");
1669     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1670 
1671     uint32_t rendererState = napiAudioRenderer->audioRenderer_->GetStatus();
1672     napi_status status = NapiParamUtils::SetValueInt32(env, rendererState, result);
1673     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "SetValueInt32 failed");
1674     return result;
1675 }
1676 
On(napi_env env,napi_callback_info info)1677 napi_value NapiAudioRenderer::On(napi_env env, napi_callback_info info)
1678 {
1679     const size_t requireArgc = ARGS_TWO;
1680     size_t argc = ARGS_THREE;
1681 
1682     napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
1683     napi_value jsThis = nullptr;
1684     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
1685     CHECK_AND_RETURN_RET_LOG(status == napi_ok,
1686         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM), "status error");
1687     CHECK_AND_RETURN_RET_LOG(argc >= requireArgc, NapiAudioError::ThrowErrorAndReturn(env,
1688         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "requireArgc is invaild");
1689 
1690     napi_valuetype eventType = napi_undefined;
1691     napi_typeof(env, argv[PARAM0], &eventType);
1692     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env,
1693         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of eventType must be string"),
1694         "eventType is invaild");
1695 
1696     std::string callbackName = NapiParamUtils::GetStringArgument(env, argv[PARAM0]);
1697     AUDIO_DEBUG_LOG("AudioRendererNapi: On callbackName: %{public}s", callbackName.c_str());
1698 
1699     napi_valuetype handler = napi_undefined;
1700     if (argc == requireArgc) {
1701         napi_typeof(env, argv[PARAM1], &handler);
1702         CHECK_AND_RETURN_RET_LOG(handler == napi_function, NapiAudioError::ThrowErrorAndReturn(env,
1703             NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of callback must be function"),
1704             "handler is invaild");
1705     } else {
1706         napi_valuetype paramArg1 = napi_undefined;
1707         napi_typeof(env, argv[PARAM1], &paramArg1);
1708         napi_valuetype expectedValType = napi_number;  // Default. Reset it with 'callbackName' if check, if required.
1709         CHECK_AND_RETURN_RET_LOG(paramArg1 == expectedValType, NapiAudioError::ThrowErrorAndReturn(env,
1710             NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of frame must be number"),
1711             "paramArg1 is invaild");
1712         const int32_t arg2 = ARGS_TWO;
1713         napi_typeof(env, argv[arg2], &handler);
1714         CHECK_AND_RETURN_RET_LOG(handler == napi_function, NapiAudioError::ThrowErrorAndReturn(env,
1715             NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of callback must be function"),
1716             "handler2 is invaild");
1717     }
1718 
1719     return RegisterCallback(env, jsThis, argv, callbackName);
1720 }
1721 
Off(napi_env env,napi_callback_info info)1722 napi_value NapiAudioRenderer::Off(napi_env env, napi_callback_info info)
1723 {
1724     const size_t requireArgc = ARGS_TWO;
1725     size_t argc = ARGS_THREE;
1726 
1727     napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
1728     napi_value jsThis = nullptr;
1729     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
1730     CHECK_AND_RETURN_RET_LOG(status == napi_ok,
1731         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM), "status error");
1732     CHECK_AND_RETURN_RET_LOG(argc <= requireArgc, NapiAudioError::ThrowErrorAndReturn(env,
1733         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argc is invaild");
1734 
1735     napi_valuetype eventType = napi_undefined;
1736     napi_typeof(env, argv[PARAM0], &eventType);
1737     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env,
1738         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of eventType must be string"),
1739         "eventType is invaild");
1740 
1741     std::string callbackName = NapiParamUtils::GetStringArgument(env, argv[PARAM0]);
1742     AUDIO_DEBUG_LOG("AudioRendererNapi: Off callbackName: %{public}s", callbackName.c_str());
1743 
1744     return UnregisterCallback(env, jsThis, argc, argv, callbackName);
1745 }
1746 
SetSilentModeAndMixWithOthers(napi_env env,napi_callback_info info)1747 napi_value NapiAudioRenderer::SetSilentModeAndMixWithOthers(napi_env env, napi_callback_info info)
1748 {
1749     napi_value result = nullptr;
1750     size_t argc = ARGS_ONE;
1751     napi_value argv[ARGS_ONE] = {};
1752     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, argv);
1753     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
1754         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argcCount invalid");
1755 
1756     napi_valuetype valueType = napi_undefined;
1757     napi_typeof(env, argv[PARAM0], &valueType);
1758     CHECK_AND_RETURN_RET_LOG(valueType == napi_boolean, NapiAudioError::ThrowErrorAndReturn(env,
1759         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of on must be bool"),
1760         "valueType param0 invalid");
1761 
1762     bool on;
1763     NapiParamUtils::GetValueBoolean(env, on, argv[PARAM0]);
1764 
1765     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1766     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1767     napiAudioRenderer->audioRenderer_->SetSilentModeAndMixWithOthers(on);
1768     return result;
1769 }
1770 
GetSilentModeAndMixWithOthers(napi_env env,napi_callback_info info)1771 napi_value NapiAudioRenderer::GetSilentModeAndMixWithOthers(napi_env env, napi_callback_info info)
1772 {
1773     napi_value result = nullptr;
1774     size_t argc = ARGS_ONE;
1775     napi_value argv[ARGS_ONE] = {};
1776     auto *napiAudioRenderer = GetParamWithSync(env, info, argc, argv);
1777     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer != nullptr, result, "napiAudioRenderer is nullptr");
1778     CHECK_AND_RETURN_RET_LOG(napiAudioRenderer->audioRenderer_ != nullptr, result, "audioRenderer_ is nullptr");
1779 
1780     bool on = napiAudioRenderer->audioRenderer_->GetSilentModeAndMixWithOthers();
1781     napi_get_boolean(env, on, &result);
1782     return result;
1783 }
1784 
SetDefaultOutputDevice(napi_env env,napi_callback_info info)1785 napi_value NapiAudioRenderer::SetDefaultOutputDevice(napi_env env, napi_callback_info info)
1786 {
1787     auto context = std::make_shared<AudioRendererAsyncContext>();
1788     if (context == nullptr) {
1789         NapiAudioError::ThrowError(env, "SetDefaultOutputDevice failed : no memory",
1790             NAPI_ERR_NO_MEMORY);
1791         return NapiParamUtils::GetUndefinedValue(env);
1792     }
1793 
1794     auto inputParser = [env, context](size_t argc, napi_value *argv) {
1795         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
1796             NAPI_ERR_INPUT_INVALID);
1797         context->status = NapiParamUtils::GetValueInt32(env, context->deviceType, argv[PARAM0]);
1798         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
1799             "incorrect parameter types: The type of mode must be number", NAPI_ERR_INPUT_INVALID);
1800         NAPI_CHECK_ARGS_RETURN_VOID(context,
1801             NapiAudioEnum::IsLegalInputArgumentDefaultOutputDeviceType(context->deviceType),
1802             "parameter verification failed: The param of mode must be enum deviceType",
1803             NAPI_ERR_INVALID_PARAM);
1804     };
1805     context->GetCbInfo(env, info, inputParser);
1806 
1807     if ((context->status != napi_ok) && (context->errCode == NAPI_ERR_INPUT_INVALID ||
1808         context->errCode == NAPI_ERR_INVALID_PARAM)) {
1809         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
1810         return NapiParamUtils::GetUndefinedValue(env);
1811     }
1812 
1813     auto executor = [context]() {
1814         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1815         auto obj = reinterpret_cast<NapiAudioRenderer*>(context->native);
1816         ObjectRefMap objectGuard(obj);
1817         auto *napiAudioRenderer = objectGuard.GetPtr();
1818         CHECK_AND_RETURN_LOG(CheckAudioRendererStatus(napiAudioRenderer, context),
1819             "context object state is error.");
1820         DeviceType deviceType = static_cast<DeviceType>(context->deviceType);
1821         context->intValue = napiAudioRenderer->audioRenderer_->SetDefaultOutputDevice(deviceType);
1822         if (context->intValue != SUCCESS) {
1823             context->SignError(NAPI_ERR_ILLEGAL_STATE);
1824         }
1825     };
1826 
1827     auto complete = [env](napi_value &output) {
1828         output = NapiParamUtils::GetUndefinedValue(env);
1829     };
1830     return NapiAsyncWork::Enqueue(env, context, "SetDefaultOutputDevice", executor, complete);
1831 }
1832 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * argv,const std::string & cbName)1833 napi_value NapiAudioRenderer::RegisterCallback(napi_env env, napi_value jsThis,
1834     napi_value *argv, const std::string &cbName)
1835 {
1836     NapiAudioRenderer *napiRenderer = nullptr;
1837     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiRenderer));
1838     CHECK_AND_RETURN_RET_LOG(status == napi_ok,
1839         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM), "status error");
1840     CHECK_AND_RETURN_RET_LOG(napiRenderer != nullptr,
1841         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY), "rendererNapi is nullptr");
1842     CHECK_AND_RETURN_RET_LOG(napiRenderer->audioRenderer_ != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
1843         NAPI_ERR_NO_MEMORY), "audioRenderer_ is nullptr");
1844 
1845     napi_value result = nullptr;
1846     napi_get_undefined(env, &result);
1847 
1848     if (!cbName.compare(INTERRUPT_CALLBACK_NAME) ||
1849         !cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME) ||
1850         !cbName.compare(STATE_CHANGE_CALLBACK_NAME)) {
1851         result = RegisterRendererCallback(env, argv, cbName, napiRenderer);
1852     } else if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
1853         result = RegisterPositionCallback(env, argv, cbName, napiRenderer);
1854     } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
1855         result = RegisterPeriodPositionCallback(env, argv, cbName, napiRenderer);
1856     } else if (!cbName.compare(DATA_REQUEST_CALLBACK_NAME)) {
1857         result = RegisterDataRequestCallback(env, argv, cbName, napiRenderer);
1858     } else if (!cbName.compare(DEVICECHANGE_CALLBACK_NAME)) {
1859         RegisterRendererDeviceChangeCallback(env, argv, napiRenderer);
1860     } else if (cbName == OUTPUT_DEVICECHANGE_WITH_INFO) {
1861         RegisterRendererOutputDeviceChangeWithInfoCallback(env, argv, napiRenderer);
1862     } else if (!cbName.compare(WRITE_DATA_CALLBACK_NAME)) {
1863         RegisterRendererWriteDataCallback(env, argv, cbName, napiRenderer);
1864     } else {
1865         bool unknownCallback = true;
1866         CHECK_AND_RETURN_RET_LOG(!unknownCallback, NapiAudioError::ThrowErrorAndReturn(env,
1867             NAPI_ERROR_INVALID_PARAM,
1868             "parameter verification failed: The param of type is not supported"), "audioRenderer_ is nullptr");
1869     }
1870 
1871     return result;
1872 }
1873 
UnregisterCallback(napi_env env,napi_value jsThis,size_t argc,napi_value * argv,const std::string & cbName)1874 napi_value NapiAudioRenderer::UnregisterCallback(napi_env env, napi_value jsThis, size_t argc, napi_value *argv,
1875     const std::string &cbName)
1876 {
1877     NapiAudioRenderer *napiRenderer = nullptr;
1878     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiRenderer));
1879     CHECK_AND_RETURN_RET_LOG(status == napi_ok,
1880         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM), "status error");
1881     CHECK_AND_RETURN_RET_LOG(napiRenderer != nullptr,
1882         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY), "napiRenderer is nullptr");
1883     CHECK_AND_RETURN_RET_LOG(napiRenderer->audioRenderer_ != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
1884         NAPI_ERR_NO_MEMORY), "audioRenderer_ is nullptr");
1885 
1886     if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
1887         UnregisterPositionCallback(env, argc, cbName, argv, napiRenderer);
1888     } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
1889         UnregisterPeriodPositionCallback(env, argc, cbName, argv, napiRenderer);
1890     } else if (!cbName.compare(DEVICECHANGE_CALLBACK_NAME)) {
1891         UnregisterRendererDeviceChangeCallback(env, argc, argv, napiRenderer);
1892     } else if (!cbName.compare(INTERRUPT_CALLBACK_NAME) ||
1893         !cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME) ||
1894         !cbName.compare(STATE_CHANGE_CALLBACK_NAME)) {
1895         UnregisterRendererCallback(env, argc, cbName, argv, napiRenderer);
1896     } else if (!cbName.compare(DATA_REQUEST_CALLBACK_NAME)) {
1897         UnregisterDataRequestCallback(env, argc, cbName, argv, napiRenderer);
1898     } else if (cbName == OUTPUT_DEVICECHANGE_WITH_INFO) {
1899         UnregisterRendererOutputDeviceChangeWithInfoCallback(env, argc, argv, napiRenderer);
1900     } else if (!cbName.compare(WRITE_DATA_CALLBACK_NAME)) {
1901         UnregisterRendererWriteDataCallback(env, argc, argv, napiRenderer);
1902     } else {
1903         bool unknownCallback = true;
1904         CHECK_AND_RETURN_RET_LOG(!unknownCallback, NapiAudioError::ThrowErrorAndReturn(env,
1905             NAPI_ERR_INVALID_PARAM,
1906             "parameter verification failed: The param of type is not supported"), "cbName is invaild");
1907     }
1908 
1909     napi_value result = nullptr;
1910     napi_get_undefined(env, &result);
1911     return result;
1912 }
1913 
RegisterRendererCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioRenderer * napiRenderer)1914 napi_value NapiAudioRenderer::RegisterRendererCallback(napi_env env, napi_value *argv,
1915     const std::string &cbName, NapiAudioRenderer *napiRenderer)
1916 {
1917     CHECK_AND_RETURN_RET_LOG(napiRenderer->callbackNapi_ != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
1918         NAPI_ERR_NO_MEMORY), "callbackNapi_ is nullptr");
1919 
1920     std::shared_ptr<NapiAudioRendererCallback> cb =
1921         std::static_pointer_cast<NapiAudioRendererCallback>(napiRenderer->callbackNapi_);
1922     cb->SaveCallbackReference(cbName, argv[PARAM1]);
1923     if (cbName == INTERRUPT_CALLBACK_NAME || cbName == AUDIO_INTERRUPT_CALLBACK_NAME) {
1924         if (!cb->GetArInterruptTsfnFlag()) {
1925             cb->CreateArInterrupt(env);
1926         }
1927     } else if (cbName == STATE_CHANGE_CALLBACK_NAME) {
1928         if (!cb->GetArStateChangeTsfnFlag()) {
1929             cb->CreateArStateChange(env);
1930         }
1931     }
1932 
1933     napi_value result = nullptr;
1934     napi_get_undefined(env, &result);
1935     return result;
1936 }
1937 
RegisterPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioRenderer * napiRenderer)1938 napi_value NapiAudioRenderer::RegisterPositionCallback(napi_env env, napi_value *argv,
1939     const std::string &cbName, NapiAudioRenderer *napiRenderer)
1940 {
1941     int64_t markPosition = 0;
1942     NapiParamUtils::GetValueInt64(env, markPosition, argv[PARAM1]);
1943 
1944     CHECK_AND_RETURN_RET_LOG(markPosition > 0, NapiAudioError::ThrowErrorAndReturn(env,
1945         NAPI_ERR_INPUT_INVALID, "parameter verification failed: The param of frame is not supported"),
1946         "Mark Position value not supported!!");
1947     napiRenderer->positionCbNapi_ = std::make_shared<NapiRendererPositionCallback>(env);
1948     CHECK_AND_RETURN_RET_LOG(napiRenderer->positionCbNapi_ != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
1949         NAPI_ERR_NO_MEMORY), "positionCbNapi_ is nullptr");
1950     int32_t ret = napiRenderer->audioRenderer_->SetRendererPositionCallback(markPosition,
1951         napiRenderer->positionCbNapi_);
1952     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM),
1953         "SetRendererPositionCallback fail");
1954 
1955     std::shared_ptr<NapiRendererPositionCallback> cb =
1956         std::static_pointer_cast<NapiRendererPositionCallback>(napiRenderer->positionCbNapi_);
1957     cb->SaveCallbackReference(cbName, argv[PARAM2]);
1958     if (!cb->GetMarkReachedTsfnFlag()) {
1959         cb->CreateMarkReachedTsfn(env);
1960     }
1961 
1962     napi_value result = nullptr;
1963     napi_get_undefined(env, &result);
1964     return result;
1965 }
1966 
UnregisterPositionCallback(napi_env env,size_t argc,const std::string & cbName,napi_value * argv,NapiAudioRenderer * napiRenderer)1967 void NapiAudioRenderer::UnregisterPositionCallback(napi_env env, size_t argc,
1968     const std::string &cbName, napi_value *argv, NapiAudioRenderer *napiRenderer)
1969 {
1970     CHECK_AND_RETURN_LOG(napiRenderer->positionCbNapi_ != nullptr, "rendererCallbackNapi is nullptr");
1971 
1972     std::shared_ptr<NapiRendererPositionCallback> cb =
1973         std::static_pointer_cast<NapiRendererPositionCallback>(napiRenderer->positionCbNapi_);
1974     std::function<int32_t(std::shared_ptr<NapiRendererPositionCallback> callbackPtr,
1975         napi_value callback)> removeFunction =
1976         [&napiRenderer] (std::shared_ptr<NapiRendererPositionCallback> callbackPtr, napi_value callback) {
1977             napiRenderer->audioRenderer_->UnsetRendererPositionCallback();
1978             napiRenderer->positionCbNapi_ = nullptr;
1979             return SUCCESS;
1980         };
1981     auto callback = GetCallback(argc, argv);
1982     UnregisterAudioRendererSingletonCallbackTemplate(env, callback, cbName, cb, removeFunction);
1983     AUDIO_DEBUG_LOG("UnregisterRendererPositionCallback is successful");
1984 }
1985 
RegisterPeriodPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioRenderer * napiRenderer)1986 napi_value NapiAudioRenderer::RegisterPeriodPositionCallback(napi_env env, napi_value *argv,
1987     const std::string &cbName, NapiAudioRenderer *napiRenderer)
1988 {
1989     int64_t frameCount = 0;
1990     NapiParamUtils::GetValueInt64(env, frameCount, argv[PARAM1]);
1991 
1992     if (frameCount > 0) {
1993         if (napiRenderer->periodPositionCbNapi_ == nullptr) {
1994             napiRenderer->periodPositionCbNapi_ = std::make_shared<NapiRendererPeriodPositionCallback>(env);
1995             CHECK_AND_RETURN_RET_LOG(napiRenderer->periodPositionCbNapi_ != nullptr,
1996                 NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY),
1997                 "periodPositionCbNapi_ is nullptr, No memery");
1998 
1999             int32_t ret = napiRenderer->audioRenderer_->SetRendererPeriodPositionCallback(frameCount,
2000                 napiRenderer->periodPositionCbNapi_);
2001             CHECK_AND_RETURN_RET_LOG(ret == SUCCESS,
2002                 NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM),
2003                 "SetRendererPeriodPositionCallback failed");
2004 
2005             std::shared_ptr<NapiRendererPeriodPositionCallback> cb =
2006                 std::static_pointer_cast<NapiRendererPeriodPositionCallback>(napiRenderer->periodPositionCbNapi_);
2007             cb->SaveCallbackReference(cbName, argv[PARAM2]);
2008             cb->CreatePeriodReachTsfn(env);
2009         } else {
2010             AUDIO_DEBUG_LOG("periodReach already subscribed.");
2011         }
2012     } else {
2013         AUDIO_ERR_LOG("frameCount value not supported!!");
2014     }
2015 
2016     napi_value result = nullptr;
2017     napi_get_undefined(env, &result);
2018     return result;
2019 }
2020 
UnregisterPeriodPositionCallback(napi_env env,size_t argc,const std::string & cbName,napi_value * argv,NapiAudioRenderer * napiRenderer)2021 void NapiAudioRenderer::UnregisterPeriodPositionCallback(napi_env env, size_t argc,
2022     const std::string &cbName, napi_value *argv, NapiAudioRenderer *napiRenderer)
2023 {
2024     CHECK_AND_RETURN_LOG(napiRenderer->periodPositionCbNapi_ != nullptr, "periodPositionCbNapi is nullptr");
2025 
2026     std::shared_ptr<NapiRendererPeriodPositionCallback> cb =
2027         std::static_pointer_cast<NapiRendererPeriodPositionCallback>(napiRenderer->periodPositionCbNapi_);
2028     std::function<int32_t(std::shared_ptr<NapiRendererPeriodPositionCallback> callbackPtr,
2029         napi_value callback)> removeFunction =
2030         [&napiRenderer] (std::shared_ptr<NapiRendererPeriodPositionCallback> callbackPtr, napi_value callback) {
2031             napiRenderer->audioRenderer_->UnsetRendererPeriodPositionCallback();
2032             napiRenderer->periodPositionCbNapi_ = nullptr;
2033             return SUCCESS;
2034         };
2035     auto callback = GetCallback(argc, argv);
2036     UnregisterAudioRendererSingletonCallbackTemplate(env, callback, cbName, cb, removeFunction);
2037     AUDIO_DEBUG_LOG("UnregisterRendererPeriodPositionCallback is successful");
2038 }
2039 
RegisterDataRequestCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioRenderer * napiRenderer)2040 napi_value NapiAudioRenderer::RegisterDataRequestCallback(napi_env env, napi_value *argv,
2041     const std::string &cbName, NapiAudioRenderer *napiRenderer)
2042 {
2043     CHECK_AND_RETURN_RET_LOG(napiRenderer->dataRequestCbNapi_ == nullptr,
2044         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_ILLEGAL_STATE),
2045             "dataRequest already subscribed.");
2046 
2047     napiRenderer->dataRequestCbNapi_ = std::make_shared<NapiRendererDataRequestCallback>(env, napiRenderer);
2048     napiRenderer->audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK);
2049     CHECK_AND_RETURN_RET_LOG(napiRenderer->dataRequestCbNapi_ != nullptr,
2050         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY), "dataRequestCbNapi_ is nullptr");
2051     int32_t ret = napiRenderer->audioRenderer_->SetRendererWriteCallback(napiRenderer->dataRequestCbNapi_);
2052     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS,
2053         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM), "SetRendererWriteCallback failed");
2054     std::shared_ptr<NapiRendererDataRequestCallback> cb =
2055         std::static_pointer_cast<NapiRendererDataRequestCallback>(napiRenderer->dataRequestCbNapi_);
2056     cb->SaveCallbackReference(cbName, argv[PARAM1]);
2057     cb->CreateWriteDataTsfn(env);
2058 
2059     napi_value result = nullptr;
2060     napi_get_undefined(env, &result);
2061     return result;
2062 }
2063 
UnregisterDataRequestCallback(napi_env env,size_t argc,const std::string & cbName,napi_value * argv,NapiAudioRenderer * napiRenderer)2064 void NapiAudioRenderer::UnregisterDataRequestCallback(napi_env env, size_t argc,
2065     const std::string &cbName, napi_value *argv, NapiAudioRenderer *napiRenderer)
2066 {
2067     CHECK_AND_RETURN_LOG(napiRenderer->dataRequestCbNapi_ != nullptr, "rendererCallbackNapi is nullptr");
2068 
2069     std::shared_ptr<NapiRendererDataRequestCallback> cb =
2070         std::static_pointer_cast<NapiRendererDataRequestCallback>(napiRenderer->dataRequestCbNapi_);
2071     std::function<int32_t(std::shared_ptr<NapiRendererDataRequestCallback> callbackPtr,
2072         napi_value callback)> removeFunction =
2073         [&napiRenderer] (std::shared_ptr<NapiRendererDataRequestCallback> callbackPtr, napi_value callback) {
2074             napiRenderer->dataRequestCbNapi_ = nullptr;
2075             return SUCCESS;
2076         };
2077     auto callback = GetCallback(argc, argv);
2078     UnregisterAudioRendererSingletonCallbackTemplate(env, callback, cbName, cb, removeFunction);
2079     AUDIO_DEBUG_LOG("UnregisterRendererDataRequestCallback is successful");
2080 }
2081 
RegisterRendererDeviceChangeCallback(napi_env env,napi_value * argv,NapiAudioRenderer * napiRenderer)2082 void NapiAudioRenderer::RegisterRendererDeviceChangeCallback(napi_env env, napi_value *argv,
2083     NapiAudioRenderer *napiRenderer)
2084 {
2085     if (!napiRenderer->rendererDeviceChangeCallbackNapi_) {
2086         napiRenderer->rendererDeviceChangeCallbackNapi_ = std::make_shared<NapiAudioRendererDeviceChangeCallback>(env);
2087         CHECK_AND_RETURN_LOG(napiRenderer->rendererDeviceChangeCallbackNapi_ != nullptr,
2088             "rendererDeviceChangeCallbackNapi_ is nullptr, No memery");
2089 
2090         int32_t ret = napiRenderer->audioRenderer_->RegisterOutputDeviceChangeWithInfoCallback(
2091             napiRenderer->rendererDeviceChangeCallbackNapi_);
2092         CHECK_AND_RETURN_LOG(ret == SUCCESS,
2093             "Registering of Renderer Device Change Callback Failed");
2094     }
2095 
2096     if (!napiRenderer->rendererPolicyServiceDiedCallbackNapi_) {
2097         napiRenderer->rendererPolicyServiceDiedCallbackNapi_ =
2098             std::make_shared<NapiAudioRendererPolicyServiceDiedCallback>(napiRenderer);
2099         CHECK_AND_RETURN_LOG(napiRenderer->rendererPolicyServiceDiedCallbackNapi_ != nullptr,
2100             "Registering of Renderer Device Change Callback Failed");
2101 
2102         int32_t ret = napiRenderer->audioRenderer_->RegisterAudioPolicyServerDiedCb(getpid(),
2103             napiRenderer->rendererPolicyServiceDiedCallbackNapi_);
2104         CHECK_AND_RETURN_LOG(ret == SUCCESS, "Registering of AudioPolicyService Died Change Callback Failed");
2105     }
2106 
2107     std::shared_ptr<NapiAudioRendererDeviceChangeCallback> cb =
2108         std::static_pointer_cast<NapiAudioRendererDeviceChangeCallback>(
2109         napiRenderer->rendererDeviceChangeCallbackNapi_);
2110     cb->AddCallbackReference(argv[PARAM1]);
2111     if (!cb->GetRendererDeviceChangeTsfnFlag()) {
2112         cb->CreateRendererDeviceChangeTsfn(env);
2113     }
2114     AUDIO_INFO_LOG("RegisterRendererStateChangeCallback is successful");
2115 }
2116 
UnregisterRendererCallback(napi_env env,size_t argc,const std::string & cbName,napi_value * argv,NapiAudioRenderer * napiRenderer)2117 void NapiAudioRenderer::UnregisterRendererCallback(napi_env env, size_t argc,
2118     const std::string &cbName, napi_value *argv, NapiAudioRenderer *napiRenderer)
2119 {
2120     CHECK_AND_RETURN_LOG(napiRenderer->callbackNapi_ != nullptr, "napiRendererCallback is nullptr");
2121 
2122     std::shared_ptr<NapiAudioRendererCallback> cb =
2123         std::static_pointer_cast<NapiAudioRendererCallback>(napiRenderer->callbackNapi_);
2124     auto callback = GetCallback(argc, argv);
2125     UnregisterAudioRendererSingletonCallbackTemplate(env, callback, cbName, cb);
2126     AUDIO_DEBUG_LOG("UnregisterRendererCallback is successful");
2127 }
2128 
UnregisterRendererDeviceChangeCallback(napi_env env,size_t argc,napi_value * argv,NapiAudioRenderer * napiRenderer)2129 void NapiAudioRenderer::UnregisterRendererDeviceChangeCallback(napi_env env, size_t argc,
2130     napi_value *argv, NapiAudioRenderer *napiRenderer)
2131 {
2132     napi_value callback = nullptr;
2133 
2134     if (argc == ARGS_TWO) {
2135         callback = argv[PARAM1];
2136     }
2137 
2138     CHECK_AND_RETURN_LOG(napiRenderer->rendererDeviceChangeCallbackNapi_ != nullptr,
2139         "rendererDeviceChangeCallbackNapi_ is nullptr, return");
2140 
2141     CHECK_AND_RETURN_LOG(napiRenderer->rendererPolicyServiceDiedCallbackNapi_ != nullptr,
2142         "rendererPolicyServiceDiedCallbackNapi_ is nullptr, return");
2143 
2144     std::shared_ptr<NapiAudioRendererDeviceChangeCallback> cb =
2145         std::static_pointer_cast<NapiAudioRendererDeviceChangeCallback>(
2146             napiRenderer->rendererDeviceChangeCallbackNapi_);
2147 
2148     cb->RemoveCallbackReference(env, callback);
2149 
2150     if (callback == nullptr || cb->GetCallbackListSize() == 0) {
2151         int32_t ret = napiRenderer->audioRenderer_->UnregisterOutputDeviceChangeWithInfoCallback(cb);
2152         CHECK_AND_RETURN_LOG(ret == SUCCESS, "unregister renderer device change callback failed");
2153         ret = napiRenderer->audioRenderer_->UnregisterAudioPolicyServerDiedCb(getpid());
2154         CHECK_AND_RETURN_LOG(ret == SUCCESS, "unregister AudioPolicyServerDiedCb failed");
2155         napiRenderer->DestroyNAPICallbacks();
2156     }
2157 
2158     AUDIO_INFO_LOG("UnregisterRendererDeviceChangeCallback success!");
2159 }
2160 
RegisterRendererOutputDeviceChangeWithInfoCallback(napi_env env,napi_value * argv,NapiAudioRenderer * napiRenderer)2161 void NapiAudioRenderer::RegisterRendererOutputDeviceChangeWithInfoCallback(napi_env env, napi_value *argv,
2162     NapiAudioRenderer *napiRenderer)
2163 {
2164     if (!napiRenderer->rendererOutputDeviceChangeWithInfoCallbackNapi_) {
2165         napiRenderer->rendererOutputDeviceChangeWithInfoCallbackNapi_
2166             = std::make_shared<NapiAudioRendererOutputDeviceChangeWithInfoCallback>(env);
2167         CHECK_AND_RETURN_LOG(napiRenderer->rendererOutputDeviceChangeWithInfoCallbackNapi_ != nullptr,
2168             "rendererOutputDeviceChangeWithInfoCallbackNapi_ is nullptr, No memery");
2169 
2170         int32_t ret = napiRenderer->audioRenderer_->RegisterOutputDeviceChangeWithInfoCallback(
2171             napiRenderer->rendererOutputDeviceChangeWithInfoCallbackNapi_);
2172         CHECK_AND_RETURN_LOG(ret == SUCCESS,
2173             "Registering of Renderer Device Change Callback Failed");
2174     }
2175 
2176     if (!napiRenderer->rendererPolicyServiceDiedCallbackNapi_) {
2177         napiRenderer->rendererPolicyServiceDiedCallbackNapi_ =
2178             std::make_shared<NapiAudioRendererPolicyServiceDiedCallback>(napiRenderer);
2179         CHECK_AND_RETURN_LOG(napiRenderer->rendererPolicyServiceDiedCallbackNapi_ != nullptr,
2180             "Registering of Renderer Device Change Callback Failed");
2181 
2182         int32_t ret = napiRenderer->audioRenderer_->RegisterAudioPolicyServerDiedCb(getpid(),
2183             napiRenderer->rendererPolicyServiceDiedCallbackNapi_);
2184         CHECK_AND_RETURN_LOG(ret == SUCCESS, "Registering of AudioPolicyService Died Change Callback Failed");
2185     }
2186 
2187     std::shared_ptr<NapiAudioRendererOutputDeviceChangeWithInfoCallback> cb =
2188         napiRenderer->rendererOutputDeviceChangeWithInfoCallbackNapi_;
2189     cb->AddCallbackReference(argv[PARAM1]);
2190     if (!cb->GetOutputDeviceChangeTsfnFlag()) {
2191         cb->CreateOutputDeviceChangeTsfn(env);
2192     }
2193     AUDIO_INFO_LOG("Register Callback is successful");
2194 }
2195 
UnregisterRendererOutputDeviceChangeWithInfoCallback(napi_env env,size_t argc,napi_value * argv,NapiAudioRenderer * napiRenderer)2196 void NapiAudioRenderer::UnregisterRendererOutputDeviceChangeWithInfoCallback(napi_env env, size_t argc,
2197     napi_value *argv, NapiAudioRenderer *napiRenderer)
2198 {
2199     napi_value callback = nullptr;
2200 
2201     if (argc == ARGS_TWO) {
2202         callback = argv[PARAM1];
2203     }
2204 
2205     CHECK_AND_RETURN_LOG(napiRenderer->rendererOutputDeviceChangeWithInfoCallbackNapi_ != nullptr,
2206         "rendererDeviceChangeCallbackNapi_ is nullptr, return");
2207 
2208     CHECK_AND_RETURN_LOG(napiRenderer->rendererPolicyServiceDiedCallbackNapi_ != nullptr,
2209         "rendererPolicyServiceDiedCallbackNapi_ is nullptr, return");
2210 
2211     std::shared_ptr<NapiAudioRendererOutputDeviceChangeWithInfoCallback> cb =
2212         napiRenderer->rendererOutputDeviceChangeWithInfoCallbackNapi_;
2213     cb->RemoveCallbackReference(env, callback);
2214 
2215     if (callback == nullptr || cb->GetCallbackListSize() == 0) {
2216         int32_t ret = napiRenderer->audioRenderer_->UnregisterOutputDeviceChangeWithInfoCallback(cb);
2217         CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnregisterRendererOutputDeviceChangeWithInfoCallback failed");
2218 
2219         ret = napiRenderer->audioRenderer_->UnregisterAudioPolicyServerDiedCb(getpid());
2220         CHECK_AND_RETURN_LOG(ret == SUCCESS, "unregister AudioPolicyServerDiedCb failed");
2221 
2222         napiRenderer->DestroyNAPICallbacks();
2223     }
2224 
2225     AUDIO_INFO_LOG("UnregisterRendererOutputDeviceChangeWithInfoCallback success");
2226 }
2227 
RegisterRendererWriteDataCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioRenderer * napiRenderer)2228 void NapiAudioRenderer::RegisterRendererWriteDataCallback(napi_env env, napi_value *argv,
2229     const std::string &cbName, NapiAudioRenderer *napiRenderer)
2230 {
2231     if (napiRenderer->rendererWriteDataCallbackNapi_ != nullptr) {
2232         AUDIO_WARNING_LOG("writeData already subscribed. The old writeData function will be overwritten.");
2233     }
2234 
2235     napiRenderer->rendererWriteDataCallbackNapi_ = std::make_shared<NapiRendererWriteDataCallback>(env, napiRenderer);
2236     napiRenderer->audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK);
2237     CHECK_AND_RETURN_LOG(napiRenderer->rendererWriteDataCallbackNapi_ != nullptr, "writeDataCbNapi_ is nullpur");
2238     int32_t ret = napiRenderer->audioRenderer_->SetRendererWriteCallback(napiRenderer->rendererWriteDataCallbackNapi_);
2239     CHECK_AND_RETURN_LOG(ret == SUCCESS, "SetRendererWriteCallback failed");
2240     std::shared_ptr<NapiRendererWriteDataCallback> cb =
2241         std::static_pointer_cast<NapiRendererWriteDataCallback>(napiRenderer->rendererWriteDataCallbackNapi_);
2242     cb->AddCallbackReference(cbName, argv[PARAM1]);
2243     if (!cb->GetWriteDTsfnFlag()) {
2244         cb->CreateWriteDTsfn(env);
2245     }
2246 
2247     AUDIO_INFO_LOG("Register Callback is successful");
2248 }
2249 
UnregisterRendererWriteDataCallback(napi_env env,size_t argc,const napi_value * argv,NapiAudioRenderer * napiRenderer)2250 void NapiAudioRenderer::UnregisterRendererWriteDataCallback(napi_env env, size_t argc, const napi_value *argv,
2251     NapiAudioRenderer *napiRenderer)
2252 {
2253     napi_value callback = nullptr;
2254 
2255     if (argc == ARGS_TWO) {
2256         callback = argv[PARAM1];
2257     }
2258     CHECK_AND_RETURN_LOG(napiRenderer->rendererWriteDataCallbackNapi_ != nullptr,
2259         "napiRendererWriteDataCallback is nullptr, return");
2260 
2261     std::shared_ptr<NapiRendererWriteDataCallback> cb =
2262         std::static_pointer_cast<NapiRendererWriteDataCallback>(napiRenderer->rendererWriteDataCallbackNapi_);
2263     cb->RemoveCallbackReference(env, callback);
2264 
2265     AUDIO_INFO_LOG("Unregister Callback is successful");
2266 }
2267 
DestroyCallbacks()2268 void NapiAudioRenderer::DestroyCallbacks()
2269 {
2270     CHECK_AND_RETURN_LOG(rendererDeviceChangeCallbackNapi_ != nullptr, "rendererDeviceChangeCallbackNapi_ is nullptr");
2271     rendererDeviceChangeCallbackNapi_->RemoveAllCallbacks();
2272     DestroyNAPICallbacks();
2273 }
2274 
DestroyNAPICallbacks()2275 void NapiAudioRenderer::DestroyNAPICallbacks()
2276 {
2277     if (rendererDeviceChangeCallbackNapi_ != nullptr) {
2278         rendererDeviceChangeCallbackNapi_.reset();
2279         rendererDeviceChangeCallbackNapi_ = nullptr;
2280     }
2281 
2282     if (rendererPolicyServiceDiedCallbackNapi_ != nullptr) {
2283         rendererPolicyServiceDiedCallbackNapi_.reset();
2284         rendererPolicyServiceDiedCallbackNapi_ = nullptr;
2285     }
2286 }
2287 } // namespace AudioStandard
2288 } // namespace OHOS
2289