1 /*
2  * Copyright (c) 2023 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 "NapiAudioStreamMgr"
17 #endif
18 
19 #include "napi_audio_stream_manager.h"
20 #include "napi_audio_error.h"
21 #include "napi_param_utils.h"
22 #include "napi_audio_enum.h"
23 #include "audio_errors.h"
24 #include "audio_manager_log.h"
25 #include "napi_audio_renderer_state_callback.h"
26 #include "napi_audio_capturer_state_callback.h"
27 
28 namespace OHOS {
29 namespace AudioStandard {
30 using namespace std;
31 using namespace HiviewDFX;
32 static __thread napi_ref g_streamMgrConstructor = nullptr;
33 
NapiAudioStreamMgr()34 NapiAudioStreamMgr::NapiAudioStreamMgr()
35     : env_(nullptr), audioStreamMngr_(nullptr) {}
36 
37 NapiAudioStreamMgr::~NapiAudioStreamMgr() = default;
38 
Destructor(napi_env env,void * nativeObject,void * finalizeHint)39 void NapiAudioStreamMgr::Destructor(napi_env env, void *nativeObject, void *finalizeHint)
40 {
41     if (nativeObject != nullptr) {
42         auto obj = static_cast<NapiAudioStreamMgr *>(nativeObject);
43         ObjectRefMap<NapiAudioStreamMgr>::DecreaseRef(obj);
44     }
45     AUDIO_INFO_LOG("Destructor is successful");
46 }
47 
Construct(napi_env env,napi_callback_info info)48 napi_value NapiAudioStreamMgr::Construct(napi_env env, napi_callback_info info)
49 {
50     AUDIO_DEBUG_LOG("Construct");
51     napi_status status;
52     napi_value result = nullptr;
53     NapiParamUtils::GetUndefinedValue(env);
54 
55     size_t argc = ARGS_TWO;
56     napi_value argv[ARGS_TWO] = {0};
57     napi_value thisVar = nullptr;
58     void *data = nullptr;
59     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
60     unique_ptr<NapiAudioStreamMgr> napiStreamMgr = make_unique<NapiAudioStreamMgr>();
61     CHECK_AND_RETURN_RET_LOG(napiStreamMgr != nullptr, result, "No memory");
62 
63     napiStreamMgr->env_ = env;
64     napiStreamMgr->audioStreamMngr_ = AudioStreamManager::GetInstance();
65     napiStreamMgr->cachedClientId_ = getpid();
66     ObjectRefMap<NapiAudioStreamMgr>::Insert(napiStreamMgr.get());
67 
68     status = napi_wrap(env, thisVar, static_cast<void*>(napiStreamMgr.get()),
69         NapiAudioStreamMgr::Destructor, nullptr, nullptr);
70     if (status != napi_ok) {
71         ObjectRefMap<NapiAudioStreamMgr>::Erase(napiStreamMgr.get());
72         return result;
73     }
74     napiStreamMgr.release();
75     return thisVar;
76 }
77 
Init(napi_env env,napi_value exports)78 napi_value NapiAudioStreamMgr::Init(napi_env env, napi_value exports)
79 {
80     napi_status status;
81     napi_value constructor;
82     napi_value result = nullptr;
83     const int32_t refCount = ARGS_ONE;
84     napi_get_undefined(env, &result);
85 
86     napi_property_descriptor audio_stream_mgr_properties[] = {
87         DECLARE_NAPI_FUNCTION("on", On),
88         DECLARE_NAPI_FUNCTION("off", Off),
89         DECLARE_NAPI_FUNCTION("getCurrentAudioRendererInfoArray", GetCurrentAudioRendererInfos),
90         DECLARE_NAPI_FUNCTION("getCurrentAudioRendererInfoArraySync", GetCurrentAudioRendererInfosSync),
91         DECLARE_NAPI_FUNCTION("getCurrentAudioCapturerInfoArray", GetCurrentAudioCapturerInfos),
92         DECLARE_NAPI_FUNCTION("getCurrentAudioCapturerInfoArraySync", GetCurrentAudioCapturerInfosSync),
93         DECLARE_NAPI_FUNCTION("isAudioRendererLowLatencySupported", IsAudioRendererLowLatencySupported),
94         DECLARE_NAPI_FUNCTION("isActive", IsStreamActive),
95         DECLARE_NAPI_FUNCTION("isActiveSync", IsStreamActiveSync),
96         DECLARE_NAPI_FUNCTION("getAudioEffectInfoArray", GetEffectInfoArray),
97         DECLARE_NAPI_FUNCTION("getAudioEffectInfoArraySync", GetEffectInfoArraySync),
98         DECLARE_NAPI_FUNCTION("getHardwareOutputSamplingRate", GetHardwareOutputSamplingRate),
99     };
100 
101     status = napi_define_class(env, AUDIO_STREAM_MGR_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
102         sizeof(audio_stream_mgr_properties) / sizeof(audio_stream_mgr_properties[PARAM0]),
103         audio_stream_mgr_properties, &constructor);
104     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_define_class fail");
105 
106     status = napi_create_reference(env, constructor, refCount, &g_streamMgrConstructor);
107     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_reference fail");
108     status = napi_set_named_property(env, exports, AUDIO_STREAM_MGR_NAPI_CLASS_NAME.c_str(), constructor);
109     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_set_named_property fail");
110     return exports;
111 }
112 
CreateStreamManagerWrapper(napi_env env)113 napi_value NapiAudioStreamMgr::CreateStreamManagerWrapper(napi_env env)
114 {
115     napi_status status;
116     napi_value result = nullptr;
117     napi_value constructor;
118 
119     status = napi_get_reference_value(env, g_streamMgrConstructor, &constructor);
120     if (status != napi_ok) {
121         AUDIO_ERR_LOG("Failed in CreateStreamManagerWrapper, %{public}d", status);
122         goto fail;
123     }
124     status = napi_new_instance(env, constructor, PARAM0, nullptr, &result);
125     if (status != napi_ok) {
126         AUDIO_ERR_LOG("napi_new_instance failed, status:%{public}d", status);
127         goto fail;
128     }
129     return result;
130 
131 fail:
132     napi_get_undefined(env, &result);
133     return result;
134 }
135 
CheckContextStatus(std::shared_ptr<AudioStreamMgrAsyncContext> context)136 bool NapiAudioStreamMgr::CheckContextStatus(std::shared_ptr<AudioStreamMgrAsyncContext> context)
137 {
138     CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context object is nullptr.");
139     if (context->native == nullptr) {
140         context->SignError(NAPI_ERR_SYSTEM);
141         return false;
142     }
143     return true;
144 }
145 
CheckAudioStreamManagerStatus(NapiAudioStreamMgr * napi,std::shared_ptr<AudioStreamMgrAsyncContext> context)146 bool NapiAudioStreamMgr::CheckAudioStreamManagerStatus(NapiAudioStreamMgr *napi,
147     std::shared_ptr<AudioStreamMgrAsyncContext> context)
148 {
149     CHECK_AND_RETURN_RET_LOG(napi != nullptr, false, "napi object is nullptr.");
150     if (napi->audioStreamMngr_ == nullptr) {
151         context->SignError(NAPI_ERR_SYSTEM);
152         return false;
153     }
154     return true;
155 }
156 
GetParamWithSync(const napi_env & env,napi_callback_info info,size_t & argc,napi_value * args)157 NapiAudioStreamMgr* NapiAudioStreamMgr::GetParamWithSync(const napi_env &env, napi_callback_info info,
158     size_t &argc, napi_value *args)
159 {
160     napi_status status;
161     NapiAudioStreamMgr *napiStreamMgr = nullptr;
162     napi_value jsThis = nullptr;
163     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
164     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr,
165         "GetParamWithSync fail to napi_get_cb_info");
166 
167     status = napi_unwrap(env, jsThis, (void **)&napiStreamMgr);
168     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "napi_unwrap failed");
169     CHECK_AND_RETURN_RET_LOG(napiStreamMgr != nullptr && napiStreamMgr->audioStreamMngr_  !=
170         nullptr, napiStreamMgr, "GetParamWithSync fail to napi_unwrap");
171     return napiStreamMgr;
172 }
173 
GetCurrentAudioRendererInfos(napi_env env,napi_callback_info info)174 napi_value NapiAudioStreamMgr::GetCurrentAudioRendererInfos(napi_env env, napi_callback_info info)
175 {
176     auto context = std::make_shared<AudioStreamMgrAsyncContext>();
177     if (context == nullptr) {
178         AUDIO_ERR_LOG("GetCurrentAudioRendererInfos failed : no memory");
179         NapiAudioError::ThrowError(env, "GetCurrentAudioRendererInfos failed : no memory", NAPI_ERR_NO_MEMORY);
180         return NapiParamUtils::GetUndefinedValue(env);
181     }
182 
183     context->GetCbInfo(env, info);
184 
185     auto executor = [context]() {
186         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
187         auto obj = reinterpret_cast<NapiAudioStreamMgr*>(context->native);
188         ObjectRefMap objectGuard(obj);
189         auto *napiStreamMgr = objectGuard.GetPtr();
190         CHECK_AND_RETURN_LOG(CheckAudioStreamManagerStatus(napiStreamMgr, context),
191             "context object state is error.");
192         context->intValue = napiStreamMgr->audioStreamMngr_->GetCurrentRendererChangeInfos(
193             context->audioRendererChangeInfos);
194         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS,
195             "GetCurrentAudioRendererInfos failed", NAPI_ERR_SYSTEM);
196     };
197 
198     auto complete = [env, context](napi_value &output) {
199         NapiParamUtils::SetRendererChangeInfos(env, context->audioRendererChangeInfos, output);
200     };
201     return NapiAsyncWork::Enqueue(env, context, "GetCurrentAudioRendererInfos", executor, complete);
202 }
203 
GetCurrentAudioRendererInfosSync(napi_env env,napi_callback_info info)204 napi_value NapiAudioStreamMgr::GetCurrentAudioRendererInfosSync(napi_env env, napi_callback_info info)
205 {
206     AUDIO_INFO_LOG("GetCurrentAudioRendererInfosSync");
207     napi_value result = nullptr;
208     size_t argc = PARAM0;
209     auto *napiStreamMgr = GetParamWithSync(env, info, argc, nullptr);
210     if (argc > 0) {
211         NapiAudioError::ThrowError(env, NAPI_ERROR_INVALID_PARAM);
212     }
213     CHECK_AND_RETURN_RET_LOG(napiStreamMgr!= nullptr, result, "napiStreamMgr is nullptr");
214 
215     vector<std::unique_ptr<AudioRendererChangeInfo>> audioRendererChangeInfos;
216     int32_t ret = napiStreamMgr->audioStreamMngr_->GetCurrentRendererChangeInfos(audioRendererChangeInfos);
217     CHECK_AND_RETURN_RET_LOG(ret == AUDIO_OK, result, "GetCurrentRendererChangeInfos failure!");
218 
219     NapiParamUtils::SetRendererChangeInfos(env, audioRendererChangeInfos, result);
220 
221     return result;
222 }
223 
GetCurrentAudioCapturerInfos(napi_env env,napi_callback_info info)224 napi_value NapiAudioStreamMgr::GetCurrentAudioCapturerInfos(napi_env env, napi_callback_info info)
225 {
226     auto context = std::make_shared<AudioStreamMgrAsyncContext>();
227     if (context == nullptr) {
228         AUDIO_ERR_LOG("GetCurrentAudioCapturerInfos failed : no memory");
229         NapiAudioError::ThrowError(env, "GetCurrentAudioCapturerInfos failed : no memory", NAPI_ERR_NO_MEMORY);
230         return NapiParamUtils::GetUndefinedValue(env);
231     }
232 
233     context->GetCbInfo(env, info);
234 
235     auto executor = [context]() {
236         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
237         auto obj = reinterpret_cast<NapiAudioStreamMgr*>(context->native);
238         ObjectRefMap objectGuard(obj);
239         auto *napiStreamMgr = objectGuard.GetPtr();
240         CHECK_AND_RETURN_LOG(CheckAudioStreamManagerStatus(napiStreamMgr, context),
241             "context object state is error.");
242         napiStreamMgr->audioStreamMngr_->GetCurrentCapturerChangeInfos(
243             context->audioCapturerChangeInfos);
244     };
245 
246     auto complete = [env, context](napi_value &output) {
247         NapiParamUtils::SetCapturerChangeInfos(env, context->audioCapturerChangeInfos, output);
248     };
249     return NapiAsyncWork::Enqueue(env, context, "GetCurrentAudioCapturerInfos", executor, complete);
250 }
251 
GetCurrentAudioCapturerInfosSync(napi_env env,napi_callback_info info)252 napi_value NapiAudioStreamMgr::GetCurrentAudioCapturerInfosSync(napi_env env, napi_callback_info info)
253 {
254     AUDIO_INFO_LOG("GetCurrentAudioCapturerInfosSync");
255     napi_value result = nullptr;
256     size_t argc = PARAM0;
257     auto *napiStreamMgr = GetParamWithSync(env, info, argc, nullptr);
258     if (argc > 0) {
259         NapiAudioError::ThrowError(env, NAPI_ERROR_INVALID_PARAM);
260     }
261     CHECK_AND_RETURN_RET_LOG(napiStreamMgr!= nullptr, result, "napiStreamMgr is nullptr");
262 
263     vector<std::unique_ptr<AudioCapturerChangeInfo>> audioCapturerChangeInfos;
264     int32_t ret = napiStreamMgr->audioStreamMngr_->GetCurrentCapturerChangeInfos(audioCapturerChangeInfos);
265     if (ret != AUDIO_OK) {
266         AUDIO_ERR_LOG("GetCurrentCapturerChangeInfos failure!");
267         return result;
268     }
269     NapiParamUtils::SetCapturerChangeInfos(env, audioCapturerChangeInfos, result);
270 
271     return result;
272 }
273 
IsAudioRendererLowLatencySupported(napi_env env,napi_callback_info info)274 napi_value NapiAudioStreamMgr::IsAudioRendererLowLatencySupported(napi_env env, napi_callback_info info)
275 {
276     auto context = std::make_shared<AudioStreamMgrAsyncContext>();
277     if (context == nullptr) {
278         AUDIO_ERR_LOG("IsAudioRendererLowLatencySupported failed : no memory");
279         NapiAudioError::ThrowError(env, "IsAudioRendererLowLatencySupported failed : no memory", NAPI_ERR_NO_MEMORY);
280         return NapiParamUtils::GetUndefinedValue(env);
281     }
282 
283     auto inputParser = [env, context](size_t argc, napi_value *argv) {
284         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
285         context->status = NapiParamUtils::GetStreamInfo(env, &context->audioStreamInfo, argv[PARAM0]);
286         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "getstreaminfo failed",
287             NAPI_ERR_INVALID_PARAM);
288     };
289     context->GetCbInfo(env, info, inputParser);
290 
291     auto executor = [context]() {
292         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
293         auto obj = reinterpret_cast<NapiAudioStreamMgr*>(context->native);
294         ObjectRefMap objectGuard(obj);
295         auto *napiStreamMgr = objectGuard.GetPtr();
296         CHECK_AND_RETURN_LOG(CheckAudioStreamManagerStatus(napiStreamMgr, context),
297             "context object state is error.");
298         context->isLowLatencySupported = napiStreamMgr->audioStreamMngr_->IsAudioRendererLowLatencySupported(
299             context->audioStreamInfo);
300         context->isTrue = context->isLowLatencySupported;
301     };
302 
303     auto complete = [env, context](napi_value &output) {
304         NapiParamUtils::SetValueBoolean(env, context->isTrue, output);
305     };
306     return NapiAsyncWork::Enqueue(env, context, "IsAudioRendererLowLatencySupported", executor, complete);
307 }
308 
IsStreamActive(napi_env env,napi_callback_info info)309 napi_value NapiAudioStreamMgr::IsStreamActive(napi_env env, napi_callback_info info)
310 {
311     auto context = std::make_shared<AudioStreamMgrAsyncContext>();
312     if (context == nullptr) {
313         AUDIO_ERR_LOG("IsStreamActive failed : no memory");
314         NapiAudioError::ThrowError(env, "IsStreamActive failed : no memory", NAPI_ERR_NO_MEMORY);
315         return NapiParamUtils::GetUndefinedValue(env);
316     }
317 
318     auto inputParser = [env, context](size_t argc, napi_value *argv) {
319         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
320         context->status = NapiParamUtils::GetValueInt32(env, context->volType, argv[PARAM0]);
321         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "getvoltype failed",
322             NAPI_ERR_INVALID_PARAM);
323         if (!NapiAudioEnum::IsLegalInputArgumentVolType(context->volType)) {
324             context->SignError(context->errCode ==
325                 NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED);
326         }
327     };
328     context->GetCbInfo(env, info, inputParser);
329 
330     auto executor = [context]() {
331         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
332         auto obj = reinterpret_cast<NapiAudioStreamMgr*>(context->native);
333         ObjectRefMap objectGuard(obj);
334         auto *napiStreamMgr = objectGuard.GetPtr();
335         CHECK_AND_RETURN_LOG(CheckAudioStreamManagerStatus(napiStreamMgr, context),
336             "context object state is error.");
337         context->isActive = napiStreamMgr->audioStreamMngr_->IsStreamActive(
338             NapiAudioEnum::GetNativeAudioVolumeType(context->volType));
339         context->isTrue = context->isActive;
340     };
341 
342     auto complete = [env, context](napi_value &output) {
343         NapiParamUtils::SetValueBoolean(env, context->isTrue, output);
344     };
345     return NapiAsyncWork::Enqueue(env, context, "IsStreamActive", executor, complete);
346 }
347 
IsStreamActiveSync(napi_env env,napi_callback_info info)348 napi_value NapiAudioStreamMgr::IsStreamActiveSync(napi_env env, napi_callback_info info)
349 {
350     napi_value result = nullptr;
351     size_t argc = ARGS_ONE;
352     napi_value args[ARGS_ONE] = {};
353     auto *napiStreamMgr = GetParamWithSync(env, info, argc, args);
354     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
355         "mandatory parameters are left unspecified"), "invalid arguments");
356 
357     napi_valuetype valueType = napi_undefined;
358     napi_typeof(env, args[PARAM0], &valueType);
359     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
360         "incorrect parameter types: The type of volumeType must be number"), "invalid valueType");
361 
362     int32_t volType;
363     NapiParamUtils::GetValueInt32(env, volType, args[PARAM0]);
364     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentVolType(volType),
365         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
366         "parameter verification failed: The param of volumeType must be enum AudioVolumeType"), "get volType failed");
367 
368     CHECK_AND_RETURN_RET_LOG(napiStreamMgr != nullptr, result, "napiStreamMgr is nullptr");
369     CHECK_AND_RETURN_RET_LOG(napiStreamMgr->audioStreamMngr_ != nullptr, result,
370         "audioStreamMngr_ is nullptr");
371     bool isActive = napiStreamMgr->audioStreamMngr_->
372         IsStreamActive(NapiAudioEnum::GetNativeAudioVolumeType(volType));
373     NapiParamUtils::SetValueBoolean(env, isActive, result);
374     return result;
375 }
376 
GetEffectInfoArray(napi_env env,napi_callback_info info)377 napi_value NapiAudioStreamMgr::GetEffectInfoArray(napi_env env, napi_callback_info info)
378 {
379     auto context = std::make_shared<AudioStreamMgrAsyncContext>();
380     if (context == nullptr) {
381         AUDIO_ERR_LOG("GetEffectInfoArray failed : no memory");
382         NapiAudioError::ThrowError(env, "GetEffectInfoArray failed : no memory", NAPI_ERR_NO_MEMORY);
383         return NapiParamUtils::GetUndefinedValue(env);
384     }
385 
386     auto inputParser = [env, context](size_t argc, napi_value *argv) {
387         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
388             NAPI_ERR_INPUT_INVALID);
389         context->status = NapiParamUtils::GetValueInt32(env, context->streamUsage, argv[PARAM0]);
390         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
391             "incorrect parameter types: The type of usage must be number", NAPI_ERR_INPUT_INVALID);
392         if (!NapiAudioEnum::IsLegalInputArgumentStreamUsage(context->streamUsage)) {
393             context->SignError(NAPI_ERR_INVALID_PARAM,
394                 "parameter verification failed: The param of usage must be enum StreamUsage");
395         }
396     };
397     context->GetCbInfo(env, info, inputParser);
398 
399     if ((context->status != napi_ok) && (context->errCode == NAPI_ERR_INPUT_INVALID)) {
400         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
401         return NapiParamUtils::GetUndefinedValue(env);
402     }
403 
404     auto executor = [context]() {
405         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
406         auto obj = reinterpret_cast<NapiAudioStreamMgr*>(context->native);
407         ObjectRefMap objectGuard(obj);
408         auto *napiStreamMgr = objectGuard.GetPtr();
409         CHECK_AND_RETURN_LOG(CheckAudioStreamManagerStatus(napiStreamMgr, context),
410             "context object state is error.");
411         StreamUsage streamUsage = static_cast<StreamUsage>(context->streamUsage);
412         context->intValue = napiStreamMgr->audioStreamMngr_->GetEffectInfoArray(
413             context->audioSceneEffectInfo, streamUsage);
414         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "GetEffectInfoArray failed",
415             NAPI_ERR_SYSTEM);
416     };
417 
418     auto complete = [env, context](napi_value &output) {
419         NapiParamUtils::SetEffectInfo(env, context->audioSceneEffectInfo, output);
420     };
421     return NapiAsyncWork::Enqueue(env, context, "GetEffectInfoArray", executor, complete);
422 }
423 
GetEffectInfoArraySync(napi_env env,napi_callback_info info)424 napi_value NapiAudioStreamMgr::GetEffectInfoArraySync(napi_env env, napi_callback_info info)
425 {
426     napi_value result = nullptr;
427     size_t argc = ARGS_ONE;
428     napi_value args[ARGS_ONE] = {};
429     auto *napiStreamMgr = GetParamWithSync(env, info, argc, args);
430     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
431         "mandatory parameters are left unspecified"), "invalid arguments");
432 
433     napi_valuetype valueType = napi_undefined;
434     napi_typeof(env, args[PARAM0], &valueType);
435     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
436         "incorrect parameter types: The type of usage must be number"), "invalid valueType");
437 
438     int32_t streamUsage;
439     NapiParamUtils::GetValueInt32(env, streamUsage, args[PARAM0]);
440     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentStreamUsage(streamUsage),
441         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
442         "parameter verification failed: The param of usage must be enum StreamUsage"), "get streamUsage failed");
443 
444     CHECK_AND_RETURN_RET_LOG(napiStreamMgr != nullptr, result, "napiStreamMgr is nullptr");
445     CHECK_AND_RETURN_RET_LOG(napiStreamMgr->audioStreamMngr_ != nullptr, result,
446         "audioStreamMngr_ is nullptr");
447     AudioSceneEffectInfo audioSceneEffectInfo;
448     int32_t ret = napiStreamMgr->audioStreamMngr_->GetEffectInfoArray(audioSceneEffectInfo,
449         static_cast<StreamUsage>(streamUsage));
450     CHECK_AND_RETURN_RET_LOG(ret == AUDIO_OK, result, "GetEffectInfoArray failure!");
451     NapiParamUtils::SetEffectInfo(env, audioSceneEffectInfo, result);
452     return result;
453 }
454 
GetHardwareOutputSamplingRate(napi_env env,napi_callback_info info)455 napi_value NapiAudioStreamMgr::GetHardwareOutputSamplingRate(napi_env env, napi_callback_info info)
456 {
457     napi_value result = nullptr;
458     sptr<AudioDeviceDescriptor> deviceDescriptor = nullptr;
459     size_t argc = ARGS_ONE;
460     napi_value args[ARGS_ONE] = {};
461     auto *napiStreamMgr = GetParamWithSync(env, info, argc, args);
462     CHECK_AND_RETURN_RET_LOG(napiStreamMgr != nullptr, result, "napiStreamMgr is nullptr");
463     CHECK_AND_RETURN_RET_LOG(napiStreamMgr->audioStreamMngr_ != nullptr, result,
464         "audioStreamMngr_ is nullptr");
465 
466     if (argc < ARGS_ONE) {
467         int32_t rate = napiStreamMgr->audioStreamMngr_->GetHardwareOutputSamplingRate(deviceDescriptor);
468         NapiParamUtils::SetValueInt32(env, rate, result);
469         return result;
470     }
471 
472     deviceDescriptor = new (std::nothrow) AudioDeviceDescriptor();
473     CHECK_AND_RETURN_RET_LOG(deviceDescriptor != nullptr, result, "AudioDeviceDescriptor alloc failed!");
474 
475     bool argTransFlag = false;
476     NapiParamUtils::GetAudioDeviceDescriptor(env, deviceDescriptor, argTransFlag, args[PARAM0]);
477     CHECK_AND_RETURN_RET_LOG(argTransFlag && NapiAudioEnum::IsLegalOutputDeviceType(deviceDescriptor->deviceType_) &&
478         (deviceDescriptor->deviceRole_ == DeviceRole::OUTPUT_DEVICE),
479         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM), "invalid deviceDescriptor");
480 
481     int32_t rate = napiStreamMgr->audioStreamMngr_->GetHardwareOutputSamplingRate(deviceDescriptor);
482     NapiParamUtils::SetValueInt32(env, rate, result);
483     return result;
484 }
485 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * args,const std::string & cbName)486 void NapiAudioStreamMgr::RegisterCallback(napi_env env, napi_value jsThis,
487     napi_value *args, const std::string &cbName)
488 {
489     NapiAudioStreamMgr *napiStreamMgr = nullptr;
490     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiStreamMgr));
491     CHECK_AND_RETURN_LOG((status == napi_ok) && (napiStreamMgr != nullptr) &&
492         (napiStreamMgr->audioStreamMngr_ != nullptr), "Failed to retrieve stream mgr napi instance.");
493 
494     if (!cbName.compare(RENDERERCHANGE_CALLBACK_NAME)) {
495         RegisterRendererStateChangeCallback(env, args, cbName, napiStreamMgr);
496     } else if (!cbName.compare(CAPTURERCHANGE_CALLBACK_NAME)) {
497         RegisterCapturerStateChangeCallback(env, args, cbName, napiStreamMgr);
498     } else {
499         AUDIO_ERR_LOG("NapiAudioStreamMgr::No such callback supported");
500         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
501             "parameter verification failed: The param of type is not supported");
502     }
503 }
504 
RegisterRendererStateChangeCallback(napi_env env,napi_value * args,const std::string & cbName,NapiAudioStreamMgr * napiStreamMgr)505 void NapiAudioStreamMgr::RegisterRendererStateChangeCallback(napi_env env, napi_value *args,
506     const std::string &cbName, NapiAudioStreamMgr *napiStreamMgr)
507 {
508     if (!napiStreamMgr->rendererStateChangeCallbackNapi_) {
509         napiStreamMgr->rendererStateChangeCallbackNapi_ = std::make_shared<NapiAudioRendererStateCallback>(env);
510         CHECK_AND_RETURN_LOG(napiStreamMgr->rendererStateChangeCallbackNapi_ != nullptr,
511             "NapiAudioStreamMgr: Memory Allocation Failed !!");
512 
513         int32_t ret =
514             napiStreamMgr->audioStreamMngr_->RegisterAudioRendererEventListener(napiStreamMgr->cachedClientId_,
515             napiStreamMgr->rendererStateChangeCallbackNapi_);
516         CHECK_AND_RETURN_LOG(ret == SUCCESS,
517             "NapiAudioStreamMgr: Registering of Renderer State Change Callback Failed");
518     }
519 
520     std::shared_ptr<NapiAudioRendererStateCallback> cb =
521     std::static_pointer_cast<NapiAudioRendererStateCallback>(napiStreamMgr->rendererStateChangeCallbackNapi_);
522     cb->SaveCallbackReference(args[PARAM1]);
523 
524     AUDIO_INFO_LOG("OnRendererStateChangeCallback is successful");
525 }
526 
RegisterCapturerStateChangeCallback(napi_env env,napi_value * args,const std::string & cbName,NapiAudioStreamMgr * napiStreamMgr)527 void NapiAudioStreamMgr::RegisterCapturerStateChangeCallback(napi_env env, napi_value *args,
528     const std::string &cbName, NapiAudioStreamMgr *napiStreamMgr)
529 {
530     if (!napiStreamMgr->capturerStateChangeCallbackNapi_) {
531         napiStreamMgr->capturerStateChangeCallbackNapi_ = std::make_shared<NapiAudioCapturerStateCallback>(env);
532         CHECK_AND_RETURN_LOG(napiStreamMgr->capturerStateChangeCallbackNapi_ != nullptr,
533             "Memory Allocation Failed !!");
534 
535         int32_t ret =
536             napiStreamMgr->audioStreamMngr_->RegisterAudioCapturerEventListener(napiStreamMgr->cachedClientId_,
537             napiStreamMgr->capturerStateChangeCallbackNapi_);
538         CHECK_AND_RETURN_LOG(ret == SUCCESS,
539             "Registering of Capturer State Change Callback Failed");
540     }
541     std::lock_guard<std::mutex> lock(napiStreamMgr->capturerStateChangeCallbackNapi_->cbMutex_);
542 
543     std::shared_ptr<NapiAudioCapturerStateCallback> cb =
544         std::static_pointer_cast<NapiAudioCapturerStateCallback>(napiStreamMgr->capturerStateChangeCallbackNapi_);
545     cb->SaveCallbackReference(args[PARAM1]);
546 
547     AUDIO_INFO_LOG("OnCapturerStateChangeCallback is successful");
548 }
549 
On(napi_env env,napi_callback_info info)550 napi_value NapiAudioStreamMgr::On(napi_env env, napi_callback_info info)
551 {
552     const size_t requireArgc = ARGS_TWO;
553     size_t argc = ARGS_THREE;
554 
555     napi_value undefinedResult = nullptr;
556     napi_get_undefined(env, &undefinedResult);
557 
558     napi_value args[requireArgc + PARAM1] = {nullptr, nullptr, nullptr};
559     napi_value jsThis = nullptr;
560     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
561     CHECK_AND_RETURN_RET_LOG(status == napi_ok && argc == requireArgc, NapiAudioError::ThrowErrorAndReturn(env,
562         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "status or arguments error");
563 
564     napi_valuetype eventType = napi_undefined;
565     napi_typeof(env, args[PARAM0], &eventType);
566     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
567         "incorrect parameter types: The type of eventType must be string"), "eventType error");
568 
569     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
570     AUDIO_DEBUG_LOG("AudioStreamMgrNapi: On callbackName: %{public}s", callbackName.c_str());
571 
572     napi_valuetype handler = napi_undefined;
573 
574     napi_typeof(env, args[PARAM1], &handler);
575     CHECK_AND_RETURN_RET_LOG(handler == napi_function, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
576         "incorrect parameter types: The type of callback must be function"), "handler is invalid");
577 
578     RegisterCallback(env, jsThis, args, callbackName);
579     return undefinedResult;
580 }
581 
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & cbName)582 void NapiAudioStreamMgr::UnregisterCallback(napi_env env, napi_value jsThis, const std::string &cbName)
583 {
584     AUDIO_INFO_LOG("UnregisterCallback");
585     NapiAudioStreamMgr *napiStreamMgr = nullptr;
586     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiStreamMgr));
587     CHECK_AND_RETURN_LOG((status == napi_ok) && (napiStreamMgr != nullptr) &&
588         (napiStreamMgr->audioStreamMngr_ != nullptr), "Failed to retrieve stream mgr napi instance.");
589 
590     if (!cbName.compare(RENDERERCHANGE_CALLBACK_NAME)) {
591         int32_t ret = napiStreamMgr->audioStreamMngr_->
592             UnregisterAudioRendererEventListener(napiStreamMgr->cachedClientId_);
593         CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnRegistering of Renderer State Change Callback Failed");
594 
595         if (napiStreamMgr->rendererStateChangeCallbackNapi_ != nullptr) {
596             std::shared_ptr<NapiAudioRendererStateCallback> cb =
597                 std::static_pointer_cast<NapiAudioRendererStateCallback>(napiStreamMgr->
598                     rendererStateChangeCallbackNapi_);
599             cb->RemoveCallbackReference();
600             napiStreamMgr->rendererStateChangeCallbackNapi_.reset();
601         }
602         AUDIO_INFO_LOG("UnRegistering of renderer State Change Callback successful");
603     } else if (!cbName.compare(CAPTURERCHANGE_CALLBACK_NAME)) {
604         int32_t ret = napiStreamMgr->audioStreamMngr_->
605             UnregisterAudioCapturerEventListener(napiStreamMgr->cachedClientId_);
606         if (ret) {
607             AUDIO_ERR_LOG("UnRegistering of capturer State Change Callback Failed");
608             return;
609         }
610         if (napiStreamMgr->capturerStateChangeCallbackNapi_ != nullptr) {
611             std::lock_guard<std::mutex> lock(napiStreamMgr->capturerStateChangeCallbackNapi_->cbMutex_);
612             napiStreamMgr->capturerStateChangeCallbackNapi_.reset();
613             napiStreamMgr->capturerStateChangeCallbackNapi_ = nullptr;
614         }
615         AUDIO_INFO_LOG("UnRegistering of capturer State Change Callback successful");
616     } else {
617         AUDIO_ERR_LOG("No such callback supported");
618         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
619             "parameter verification failed: The param of type is not supported");
620     }
621 }
622 
Off(napi_env env,napi_callback_info info)623 napi_value NapiAudioStreamMgr::Off(napi_env env, napi_callback_info info)
624 {
625     const size_t requireArgc = ARGS_ONE;
626     size_t argc = ARGS_ONE;
627 
628     napi_value undefinedResult = nullptr;
629     napi_get_undefined(env, &undefinedResult);
630 
631     napi_value args[requireArgc] = {nullptr};
632     napi_value jsThis = nullptr;
633     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
634     CHECK_AND_RETURN_RET_LOG(status == napi_ok && argc >= requireArgc, NapiAudioError::ThrowErrorAndReturn(env,
635         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "status or arguments error");
636 
637     napi_valuetype eventType = napi_undefined;
638     napi_typeof(env, args[PARAM0], &eventType);
639     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
640         "incorrect parameter types: The type of eventType must be string"), "eventType error");
641 
642     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[0]);
643     AUDIO_DEBUG_LOG("NapiAudioStreamMgr: Off callbackName: %{public}s", callbackName.c_str());
644 
645     UnregisterCallback(env, jsThis, callbackName);
646     return undefinedResult;
647 }
648 }  // namespace AudioStandard
649 }  // namespace OHOS
650