• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "NapiAudioCapturer"
17 #endif
18 
19 #include "napi_audio_capturer.h"
20 
21 #include "xpower_event_js.h"
22 #include "audio_errors.h"
23 #include "audio_utils.h"
24 #include "napi_audio_error.h"
25 #include "napi_param_utils.h"
26 #include "napi_audio_enum.h"
27 #include "napi_audio_capturer_callbacks.h"
28 #include "napi_capturer_position_callback.h"
29 #include "napi_capturer_period_position_callback.h"
30 #include "napi_audio_capturer_read_data_callback.h"
31 
32 namespace OHOS {
33 namespace AudioStandard {
34 static __thread napi_ref g_capturerConstructor = nullptr;
35 std::unique_ptr<AudioCapturerOptions> NapiAudioCapturer::sCapturerOptions_ = nullptr;
36 mutex NapiAudioCapturer::createMutex_;
37 int32_t NapiAudioCapturer::isConstructSuccess_ = SUCCESS;
38 
NapiAudioCapturer()39 NapiAudioCapturer::NapiAudioCapturer()
40     : audioCapturer_(nullptr),  sourceType_(SOURCE_TYPE_MIC), env_(nullptr) {}
41 
42 NapiAudioCapturer::~NapiAudioCapturer() = default;
43 
Destructor(napi_env env,void * nativeObject,void * finalizeHint)44 void NapiAudioCapturer::Destructor(napi_env env, void *nativeObject, void *finalizeHint)
45 {
46     if (nativeObject != nullptr) {
47         auto obj = static_cast<NapiAudioCapturer *>(nativeObject);
48         ObjectRefMap<NapiAudioCapturer>::DecreaseRef(obj);
49     }
50 }
51 
InitAudioCapturer(napi_env env,napi_value & constructor)52 napi_status NapiAudioCapturer::InitAudioCapturer(napi_env env, napi_value &constructor)
53 {
54     AUDIO_DEBUG_LOG("NapiAudioCapturer::InitAudioCapturer()");
55     napi_property_descriptor audio_capturer_properties[] = {
56         DECLARE_NAPI_FUNCTION("getCapturerInfo", GetCapturerInfo),
57         DECLARE_NAPI_FUNCTION("getCapturerInfoSync", GetCapturerInfoSync),
58         DECLARE_NAPI_FUNCTION("getStreamInfo", GetStreamInfo),
59         DECLARE_NAPI_FUNCTION("getStreamInfoSync", GetStreamInfoSync),
60         DECLARE_NAPI_FUNCTION("start", Start),
61         DECLARE_NAPI_FUNCTION("read", Read),
62         DECLARE_NAPI_FUNCTION("getAudioTime", GetAudioTime),
63         DECLARE_NAPI_FUNCTION("getAudioTimeSync", GetAudioTimeSync),
64         DECLARE_NAPI_FUNCTION("stop", Stop),
65         DECLARE_NAPI_FUNCTION("release", Release),
66         DECLARE_NAPI_FUNCTION("getBufferSize", GetBufferSize),
67         DECLARE_NAPI_FUNCTION("getBufferSizeSync", GetBufferSizeSync),
68         DECLARE_NAPI_FUNCTION("getAudioStreamId", GetAudioStreamId),
69         DECLARE_NAPI_FUNCTION("getAudioStreamIdSync", GetAudioStreamIdSync),
70         DECLARE_NAPI_FUNCTION("getCurrentInputDevices", GetCurrentInputDevices),
71         DECLARE_NAPI_FUNCTION("getCurrentAudioCapturerChangeInfo", GetCurrentAudioCapturerChangeInfo),
72         DECLARE_NAPI_FUNCTION("getCurrentMicrophones", GetCurrentMicrophones),
73         DECLARE_NAPI_FUNCTION("getOverflowCount", GetOverflowCount),
74         DECLARE_NAPI_FUNCTION("getOverflowCountSync", GetOverflowCountSync),
75         DECLARE_NAPI_FUNCTION("on", On),
76         DECLARE_NAPI_FUNCTION("off", Off),
77         DECLARE_NAPI_GETTER("state", GetState),
78     };
79 
80     napi_status status = napi_define_class(env, NAPI_AUDIO_CAPTURER_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct,
81         nullptr, sizeof(audio_capturer_properties) / sizeof(audio_capturer_properties[PARAM0]),
82         audio_capturer_properties, &constructor);
83     return status;
84 }
85 
Init(napi_env env,napi_value exports)86 napi_value NapiAudioCapturer::Init(napi_env env, napi_value exports)
87 {
88     napi_value constructor;
89     napi_value result = nullptr;
90     napi_get_undefined(env, &result);
91 
92     napi_property_descriptor static_prop[] = {
93         DECLARE_NAPI_STATIC_FUNCTION("createAudioCapturer", CreateAudioCapturer),
94         DECLARE_NAPI_STATIC_FUNCTION("createAudioCapturerSync", CreateAudioCapturerSync)
95     };
96 
97     napi_status status = InitAudioCapturer(env, constructor);
98     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_define_class fail");
99     status = napi_create_reference(env, constructor, REFERENCE_CREATION_COUNT, &g_capturerConstructor);
100     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_reference fail");
101     status = napi_set_named_property(env, exports, NAPI_AUDIO_CAPTURER_CLASS_NAME.c_str(), constructor);
102     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_set_named_property fail");
103     status = napi_define_properties(env, exports, sizeof(static_prop) / sizeof(static_prop[0]), static_prop);
104     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "Failure in NapiAudioCapturer::Init()");
105 
106     return exports;
107 }
108 
CreateAudioCapturerNativeObject(napi_env env)109 unique_ptr<NapiAudioCapturer> NapiAudioCapturer::CreateAudioCapturerNativeObject(napi_env env)
110 {
111     unique_ptr<NapiAudioCapturer> napiCapturer = make_unique<NapiAudioCapturer>();
112     CHECK_AND_RETURN_RET_LOG(napiCapturer != nullptr, nullptr, "No memory");
113 
114     napiCapturer->env_ = env;
115     napiCapturer->sourceType_ = sCapturerOptions_->capturerInfo.sourceType;
116 
117     AudioCapturerOptions capturerOptions = *sCapturerOptions_;
118 
119     std::string cacheDir = "/data/storage/el2/base/temp";
120     /* NapiAudioCapturer not support other capturerFlags, only support flag 0 */
121     if (capturerOptions.capturerInfo.capturerFlags != 0) {
122         capturerOptions.capturerInfo.capturerFlags = 0;
123     }
124     napiCapturer->audioCapturer_ = AudioCapturer::Create(capturerOptions, cacheDir);
125 
126     if (napiCapturer->audioCapturer_ == nullptr) {
127         AUDIO_ERR_LOG("Capturer Create failed");
128         NapiAudioCapturer::isConstructSuccess_ = NAPI_ERR_SYSTEM;
129         napiCapturer.release();
130         return nullptr;
131     }
132     ObjectRefMap<NapiAudioCapturer>::Insert(napiCapturer.get());
133 
134     if (napiCapturer->audioCapturer_ != nullptr && napiCapturer->callbackNapi_ == nullptr) {
135         napiCapturer->callbackNapi_ = std::make_shared<NapiAudioCapturerCallback>(env);
136         CHECK_AND_RETURN_RET_LOG(napiCapturer->callbackNapi_ != nullptr, napiCapturer, "No memory");
137         int32_t ret = napiCapturer->audioCapturer_->SetCapturerCallback(napiCapturer->callbackNapi_);
138         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, napiCapturer, "Construct SetCapturerCallback failed");
139     }
140     return napiCapturer;
141 }
142 
Construct(napi_env env,napi_callback_info info)143 napi_value NapiAudioCapturer::Construct(napi_env env, napi_callback_info info)
144 {
145     napi_value result = nullptr;
146     napi_get_undefined(env, &result);
147 
148     size_t argCount = ARGS_TWO;
149     napi_value thisVar = nullptr;
150     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
151     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
152 
153     unique_ptr<NapiAudioCapturer> napiCapturer = CreateAudioCapturerNativeObject(env);
154     CHECK_AND_RETURN_RET_LOG(napiCapturer != nullptr, result, "failed to CreateAudioCapturerNativeObject");
155     status = napi_wrap(env, thisVar, static_cast<void*>(napiCapturer.get()),
156         NapiAudioCapturer::Destructor, nullptr, nullptr);
157     if (status != napi_ok) {
158         ObjectRefMap<NapiAudioCapturer>::Erase(napiCapturer.get());
159         return result;
160     }
161 
162     napiCapturer.release();
163     return thisVar;
164 }
165 
CheckContextStatus(std::shared_ptr<AudioCapturerAsyncContext> context)166 bool NapiAudioCapturer::CheckContextStatus(std::shared_ptr<AudioCapturerAsyncContext> context)
167 {
168     CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "CHECK_AND_RETURN_RET_LOG");
169     if (context->native == nullptr) {
170         context->SignError(NAPI_ERR_SYSTEM);
171         return false;
172     }
173     return true;
174 }
175 
CheckAudioCapturerStatus(NapiAudioCapturer * napi,std::shared_ptr<AudioCapturerAsyncContext> context)176 bool NapiAudioCapturer::CheckAudioCapturerStatus(NapiAudioCapturer *napi,
177     std::shared_ptr<AudioCapturerAsyncContext> context)
178 {
179     CHECK_AND_RETURN_RET_LOG(napi != nullptr, false, "CHECK_AND_RETURN_RET_LOG");
180     if (napi->audioCapturer_ == nullptr) {
181         context->SignError(NAPI_ERR_SYSTEM);
182         return false;
183     }
184     return true;
185 }
186 
GetParamWithSync(const napi_env & env,napi_callback_info info,size_t & argc,napi_value * args)187 NapiAudioCapturer* NapiAudioCapturer::GetParamWithSync(const napi_env &env, napi_callback_info info,
188     size_t &argc, napi_value *args)
189 {
190     napi_status status;
191     NapiAudioCapturer *napiAudioCapturer = nullptr;
192     napi_value jsThis = nullptr;
193 
194     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
195     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr,
196         "GetParamWithSync fail to napi_get_cb_info");
197 
198     status = napi_unwrap(env, jsThis, (void **)&napiAudioCapturer);
199     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "napi_unwrap failed");
200     CHECK_AND_RETURN_RET_LOG((napiAudioCapturer != nullptr) && (napiAudioCapturer->audioCapturer_ != nullptr),
201         napiAudioCapturer, "GetParamWithSync fail to napi_unwrap");
202 
203     return napiAudioCapturer;
204 }
205 
CreateAudioCapturerWrapper(napi_env env,const AudioCapturerOptions capturerOptions)206 napi_value NapiAudioCapturer::CreateAudioCapturerWrapper(napi_env env, const AudioCapturerOptions capturerOptions)
207 {
208     lock_guard<mutex> lock(createMutex_);
209     napi_value result = nullptr;
210     napi_value constructor = nullptr;
211 
212     napi_status status = napi_get_reference_value(env, g_capturerConstructor, &constructor);
213     if (status != napi_ok) {
214         AUDIO_ERR_LOG("napi_get_reference_value failed");
215         goto fail;
216     }
217     if (sCapturerOptions_ != nullptr) {
218         sCapturerOptions_.release();
219     }
220     sCapturerOptions_ = make_unique<AudioCapturerOptions>();
221     CHECK_AND_RETURN_RET_LOG(sCapturerOptions_ != nullptr, result, "sCapturerOptions create failed");
222     *sCapturerOptions_ = capturerOptions;
223     status = napi_new_instance(env, constructor, 0, nullptr, &result);
224     if (status != napi_ok) {
225         AUDIO_ERR_LOG("napi_new_instance failed");
226         goto fail;
227     }
228     return result;
229 
230 fail:
231     napi_get_undefined(env, &result);
232     return result;
233 }
234 
CreateAudioCapturer(napi_env env,napi_callback_info info)235 napi_value NapiAudioCapturer::CreateAudioCapturer(napi_env env, napi_callback_info info)
236 {
237     auto context = std::make_shared<AudioCapturerAsyncContext>();
238     if (context == nullptr) {
239         AUDIO_ERR_LOG("CreateAudioCapturer failed : no memory");
240         NapiAudioError::ThrowError(env, "CreateAudioCapturer failed : no memory", NAPI_ERR_NO_MEMORY);
241         return NapiParamUtils::GetUndefinedValue(env);
242     }
243 
244     auto inputParser = [env, context](size_t argc, napi_value *argv) {
245         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
246         context->status = NapiParamUtils::GetCapturerOptions(env, &context->capturerOptions, argv[PARAM0]);
247         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "CreateAudioCapturer failed",
248             NAPI_ERR_INVALID_PARAM);
249     };
250     context->GetCbInfo(env, info, inputParser);
251 
252     auto complete = [env, context](napi_value &output) {
253         output = CreateAudioCapturerWrapper(env, context->capturerOptions);
254         if (NapiAudioCapturer::isConstructSuccess_ != SUCCESS) {
255             context->SignError(NapiAudioCapturer::isConstructSuccess_);
256             NapiAudioCapturer::isConstructSuccess_ = SUCCESS;
257         }
258     };
259 
260     return NapiAsyncWork::Enqueue(env, context, "CreateAudioCapturer", nullptr, complete);
261 }
262 
CreateAudioCapturerSync(napi_env env,napi_callback_info info)263 napi_value NapiAudioCapturer::CreateAudioCapturerSync(napi_env env, napi_callback_info info)
264 {
265     size_t argc = ARGS_ONE;
266     napi_value argv[ARGS_ONE] = {};
267     napi_status status = NapiParamUtils::GetParam(env, info, argc, argv);
268     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (argc == ARGS_ONE),
269         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"),
270         "invaild param");
271 
272     napi_valuetype valueType = napi_undefined;
273     napi_typeof(env, argv[PARAM0], &valueType);
274     CHECK_AND_RETURN_RET_LOG(valueType == napi_object, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
275         "incorrect parameter types: The type of options must be number"), "invaild valueType");
276 
277     AudioCapturerOptions capturerOptions;
278     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::GetCapturerOptions(env, &capturerOptions, argv[PARAM0]) == napi_ok,
279         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
280         "parameter verification failed: The param of options must be interface AudioCapturerOptions"),
281         "get captureOptions failed");
282 
283     return NapiAudioCapturer::CreateAudioCapturerWrapper(env, capturerOptions);
284 }
285 
GetCapturerInfo(napi_env env,napi_callback_info info)286 napi_value NapiAudioCapturer::GetCapturerInfo(napi_env env, napi_callback_info info)
287 {
288     auto context = std::make_shared<AudioCapturerAsyncContext>();
289     if (context == nullptr) {
290         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
291         return NapiParamUtils::GetUndefinedValue(env);
292     }
293 
294     context->GetCbInfo(env, info);
295 
296     auto executor = [context]() {
297         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
298         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
299         ObjectRefMap objectGuard(obj);
300         auto *napiAudioCapturer = objectGuard.GetPtr();
301         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
302             "context object state is error.");
303         context->intValue = napiAudioCapturer->audioCapturer_->GetCapturerInfo(context->capturerInfo);
304         if (context->intValue != SUCCESS) {
305             context->SignError(NAPI_ERR_SYSTEM);
306         }
307     };
308 
309     auto complete = [env, context](napi_value &output) {
310         NapiParamUtils::SetCapturerInfo(env, context->capturerInfo, output);
311     };
312 
313     return NapiAsyncWork::Enqueue(env, context, "GetCapturerInfo", executor, complete);
314 }
315 
GetCapturerInfoSync(napi_env env,napi_callback_info info)316 napi_value NapiAudioCapturer::GetCapturerInfoSync(napi_env env, napi_callback_info info)
317 {
318     napi_value result = nullptr;
319     size_t argc = PARAM0;
320 
321     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
322     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID),
323         "argsCount invaild");
324 
325     AudioCapturerInfo capturerInfo;
326     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
327     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
328     int32_t ret = napiAudioCapturer->audioCapturer_->GetCapturerInfo(capturerInfo);
329 
330     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetCapturerInfoSync failure!");
331     NapiParamUtils::SetCapturerInfo(env, capturerInfo, result);
332 
333     return result;
334 }
335 
GetStreamInfo(napi_env env,napi_callback_info info)336 napi_value NapiAudioCapturer::GetStreamInfo(napi_env env, napi_callback_info info)
337 {
338     auto context = std::make_shared<AudioCapturerAsyncContext>();
339     if (context == nullptr) {
340         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
341         return NapiParamUtils::GetUndefinedValue(env);
342     }
343     context->GetCbInfo(env, info);
344 
345     auto executor = [context]() {
346         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
347         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
348         ObjectRefMap objectGuard(obj);
349         auto *napiAudioCapturer = objectGuard.GetPtr();
350         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
351             "context object state is error.");
352         context->intValue = napiAudioCapturer->audioCapturer_->GetStreamInfo(context->streamInfo);
353         if (context->intValue != SUCCESS) {
354             context->SignError(NAPI_ERR_SYSTEM);
355         }
356     };
357 
358     auto complete = [env, context](napi_value &output) {
359         NapiParamUtils::SetStreamInfo(env, context->streamInfo, output);
360     };
361 
362     return NapiAsyncWork::Enqueue(env, context, "GetStreamInfo", executor, complete);
363 }
364 
GetStreamInfoSync(napi_env env,napi_callback_info info)365 napi_value NapiAudioCapturer::GetStreamInfoSync(napi_env env, napi_callback_info info)
366 {
367     napi_value result = nullptr;
368     size_t argc = PARAM0;
369 
370     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
371     CHECK_AND_RETURN_RET_LOG(argc == PARAM0,
372         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "invaild param");
373 
374     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
375     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
376 
377     AudioStreamInfo streamInfo;
378     int32_t ret = napiAudioCapturer->audioCapturer_->GetStreamInfo(streamInfo);
379     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetStreamInfo failure!");
380 
381     NapiParamUtils::SetStreamInfo(env, streamInfo, result);
382     return result;
383 }
384 
Start(napi_env env,napi_callback_info info)385 napi_value NapiAudioCapturer::Start(napi_env env, napi_callback_info info)
386 {
387     auto context = std::make_shared<AudioCapturerAsyncContext>();
388     if (context == nullptr) {
389         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
390         return NapiParamUtils::GetUndefinedValue(env);
391     }
392     context->GetCbInfo(env, info);
393 
394     auto executor = [context]() {
395         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
396         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
397         ObjectRefMap objectGuard(obj);
398         auto *napiAudioCapturer = objectGuard.GetPtr();
399         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
400             "context object state is error.");
401         context->isTrue = napiAudioCapturer->audioCapturer_->Start();
402         if (!context->isTrue) {
403             context->SignError(NAPI_ERR_SYSTEM);
404         }
405     };
406 
407     auto complete = [env](napi_value &output) {
408         output = NapiParamUtils::GetUndefinedValue(env);
409     };
410     HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Audio");
411     return NapiAsyncWork::Enqueue(env, context, "Start", executor, complete);
412 }
413 
ReadFromNative(shared_ptr<AudioCapturerAsyncContext> context)414 napi_status NapiAudioCapturer::ReadFromNative(shared_ptr<AudioCapturerAsyncContext> context)
415 {
416     napi_status status = napi_generic_failure;
417     CHECK_AND_RETURN_RET_LOG(CheckContextStatus(context), napi_generic_failure, "context object state is error.");
418     auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
419     ObjectRefMap objectGuard(obj);
420     auto *napiAudioCapturer = objectGuard.GetPtr();
421     CHECK_AND_RETURN_RET_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context), napi_generic_failure,
422         "context object state is error.");
423     uint32_t userSize = context->userSize;
424     uint8_t *buffer = new uint8_t[userSize];
425     CHECK_AND_RETURN_RET_LOG(buffer != nullptr, status, "buffer malloc failed,no memery");
426     int32_t bytesRead = 0;
427     while (static_cast<uint32_t>(bytesRead) < context->userSize) {
428         int32_t len = napiAudioCapturer->audioCapturer_->Read(*(buffer + bytesRead),
429             userSize - bytesRead, context->isBlocking);
430         if (len >= 0) {
431             bytesRead += len;
432         } else {
433             bytesRead = len;
434             break;
435         }
436     }
437     if (bytesRead <= 0) {
438         delete [] buffer;
439         return status;
440     }
441     context->bytesRead = static_cast<size_t>(bytesRead);
442     context->buffer = buffer;
443     status = napi_ok;
444     return status;
445 }
446 
Read(napi_env env,napi_callback_info info)447 napi_value NapiAudioCapturer::Read(napi_env env, napi_callback_info info)
448 {
449     auto context = std::make_shared<AudioCapturerAsyncContext>();
450     if (context == nullptr) {
451         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
452         return NapiParamUtils::GetUndefinedValue(env);
453     }
454     auto inputParser = [env, context](size_t argc, napi_value *argv) {
455         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
456         context->status = NapiParamUtils::GetValueUInt32(env, context->userSize, argv[PARAM0]);
457         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "GetValueUInt32 userSize failed",
458             NAPI_ERR_INVALID_PARAM);
459         context->status = NapiParamUtils::GetValueBoolean(env, context->isBlocking, argv[PARAM1]);
460         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "GetValueUInt32 userSize failed",
461             NAPI_ERR_INVALID_PARAM);
462     };
463     context->GetCbInfo(env, info, inputParser);
464 
465     auto executor = [context]() {
466         context->status = ReadFromNative(context);
467         if (context->status != napi_ok) {
468             context->SignError(NAPI_ERR_SYSTEM);
469         }
470     };
471 
472     auto complete = [env, context](napi_value &output) {
473         NapiParamUtils::CreateArrayBuffer(env, context->bytesRead, context->buffer, output);
474         delete [] context->buffer;
475         context->buffer = nullptr;
476     };
477 
478     return NapiAsyncWork::Enqueue(env, context, "Read", executor, complete);
479 }
480 
GetAudioTime(napi_env env,napi_callback_info info)481 napi_value NapiAudioCapturer::GetAudioTime(napi_env env, napi_callback_info info)
482 {
483     auto context = std::make_shared<AudioCapturerAsyncContext>();
484     if (context == nullptr) {
485         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
486         return NapiParamUtils::GetUndefinedValue(env);
487     }
488     context->GetCbInfo(env, info);
489 
490     auto executor = [context]() {
491         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
492         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
493         ObjectRefMap objectGuard(obj);
494         auto *napiAudioCapturer = objectGuard.GetPtr();
495         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
496             "context object state is error.");
497         Timestamp timestamp;
498         if (napiAudioCapturer->audioCapturer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC)) {
499             const uint64_t secToNanosecond = 1000000000;
500             context->time = static_cast<uint64_t>(timestamp.time.tv_nsec) +
501                 static_cast<uint64_t>(timestamp.time.tv_sec) * secToNanosecond;
502         } else {
503             context->SignError(NAPI_ERR_SYSTEM);
504         }
505     };
506 
507     auto complete = [env, context](napi_value &output) {
508         NapiParamUtils::SetValueInt64(env, static_cast<int64_t>(context->time), output);
509     };
510 
511     return NapiAsyncWork::Enqueue(env, context, "GetAudioTime", executor, complete);
512 }
513 
GetAudioTimeSync(napi_env env,napi_callback_info info)514 napi_value NapiAudioCapturer::GetAudioTimeSync(napi_env env, napi_callback_info info)
515 {
516     napi_value result = nullptr;
517     size_t argc = PARAM0;
518 
519     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
520     CHECK_AND_RETURN_RET_LOG(argc == PARAM0,
521         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "invaild param");
522 
523     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
524     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
525 
526     Timestamp timestamp;
527     bool ret = napiAudioCapturer->audioCapturer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC);
528     CHECK_AND_RETURN_RET_LOG(ret, result, "GetAudioTime failure!");
529     const uint64_t secToNanosecond = 1000000000;
530     uint64_t time = static_cast<uint64_t>(timestamp.time.tv_nsec) +
531         static_cast<uint64_t>(timestamp.time.tv_sec) * secToNanosecond;
532 
533     NapiParamUtils::SetValueInt64(env, static_cast<int64_t>(time), result);
534     return result;
535 }
536 
Stop(napi_env env,napi_callback_info info)537 napi_value NapiAudioCapturer::Stop(napi_env env, napi_callback_info info)
538 {
539     auto context = std::make_shared<AudioCapturerAsyncContext>();
540     if (context == nullptr) {
541         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
542         return NapiParamUtils::GetUndefinedValue(env);
543     }
544     context->GetCbInfo(env, info);
545 
546     auto executor = [context]() {
547         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
548         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
549         ObjectRefMap objectGuard(obj);
550         auto *napiAudioCapturer = objectGuard.GetPtr();
551         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
552             "context object state is error.");
553         context->isTrue = napiAudioCapturer->audioCapturer_->Stop();
554         if (!context->isTrue) {
555             context->SignError(NAPI_ERR_SYSTEM);
556         }
557     };
558 
559     auto complete = [env](napi_value &output) {
560         output = NapiParamUtils::GetUndefinedValue(env);
561     };
562 
563     return NapiAsyncWork::Enqueue(env, context, "Stop", executor, complete);
564 }
565 
Release(napi_env env,napi_callback_info info)566 napi_value NapiAudioCapturer::Release(napi_env env, napi_callback_info info)
567 {
568     auto context = std::make_shared<AudioCapturerAsyncContext>();
569     if (context == nullptr) {
570         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
571         return NapiParamUtils::GetUndefinedValue(env);
572     }
573     context->GetCbInfo(env, info);
574 
575     auto executor = [context]() {
576         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
577         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
578         ObjectRefMap objectGuard(obj);
579         auto *napiAudioCapturer = objectGuard.GetPtr();
580         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
581             "context object state is error.");
582         context->isTrue = napiAudioCapturer->audioCapturer_->Release();
583         if (!context->isTrue) {
584             context->SignError(NAPI_ERR_SYSTEM);
585         }
586     };
587 
588     auto complete = [env](napi_value &output) {
589         output = NapiParamUtils::GetUndefinedValue(env);
590     };
591 
592     return NapiAsyncWork::Enqueue(env, context, "Release", executor, complete);
593 }
594 
GetBufferSize(napi_env env,napi_callback_info info)595 napi_value NapiAudioCapturer::GetBufferSize(napi_env env, napi_callback_info info)
596 {
597     auto context = std::make_shared<AudioCapturerAsyncContext>();
598     if (context == nullptr) {
599         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
600         return NapiParamUtils::GetUndefinedValue(env);
601     }
602     context->GetCbInfo(env, info);
603 
604     auto executor = [context]() {
605         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
606         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
607         ObjectRefMap objectGuard(obj);
608         auto *napiAudioCapturer = objectGuard.GetPtr();
609         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
610             "context object state is error.");
611         context->intValue = napiAudioCapturer->audioCapturer_->GetBufferSize(context->bufferSize);
612         if (context->intValue != SUCCESS) {
613             context->SignError(NAPI_ERR_SYSTEM);
614         }
615     };
616 
617     auto complete = [env, context](napi_value &output) {
618         NapiParamUtils::SetValueUInt32(env, context->bufferSize, output);
619     };
620 
621     return NapiAsyncWork::Enqueue(env, context, "GetBufferSize", executor, complete);
622 }
623 
GetBufferSizeSync(napi_env env,napi_callback_info info)624 napi_value NapiAudioCapturer::GetBufferSizeSync(napi_env env, napi_callback_info info)
625 {
626     napi_value result = nullptr;
627     size_t argc = PARAM0;
628 
629     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
630     CHECK_AND_RETURN_RET_LOG(argc == PARAM0,
631         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "invaild param");
632 
633     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
634     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
635 
636     size_t bufferSize;
637     int32_t ret = napiAudioCapturer->audioCapturer_->GetBufferSize(bufferSize);
638     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetBufferSize failure!");
639 
640     NapiParamUtils::SetValueUInt32(env, bufferSize, result);
641     return result;
642 }
643 
GetAudioStreamId(napi_env env,napi_callback_info info)644 napi_value NapiAudioCapturer::GetAudioStreamId(napi_env env, napi_callback_info info)
645 {
646     auto context = std::make_shared<AudioCapturerAsyncContext>();
647     if (context == nullptr) {
648         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
649         return NapiParamUtils::GetUndefinedValue(env);
650     }
651     context->GetCbInfo(env, info);
652 
653     auto executor = [context]() {
654         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
655         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
656         ObjectRefMap objectGuard(obj);
657         auto *napiAudioCapturer = objectGuard.GetPtr();
658         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
659             "context object state is error.");
660         context->intValue = napiAudioCapturer->audioCapturer_->GetAudioStreamId(context->audioStreamId);
661         if (context->intValue  == ERR_ILLEGAL_STATE) {
662             context->SignError(NAPI_ERR_ILLEGAL_STATE);
663         } else if (context->intValue  == ERR_INVALID_INDEX) {
664             context->SignError(NAPI_ERR_SYSTEM);
665         }
666     };
667 
668     auto complete = [env, context](napi_value &output) {
669         NapiParamUtils::SetValueUInt32(env, context->audioStreamId, output);
670     };
671 
672     return NapiAsyncWork::Enqueue(env, context, "GetAudioStreamId", executor, complete);
673 }
674 
GetAudioStreamIdSync(napi_env env,napi_callback_info info)675 napi_value NapiAudioCapturer::GetAudioStreamIdSync(napi_env env, napi_callback_info info)
676 {
677     napi_value result = nullptr;
678     size_t argc = PARAM0;
679 
680     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
681     CHECK_AND_RETURN_RET_LOG(argc == PARAM0,
682         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "invaild param");
683 
684     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
685     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
686 
687     uint32_t audioStreamId;
688     int32_t ret = napiAudioCapturer->audioCapturer_->GetAudioStreamId(audioStreamId);
689     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetAudioStreamId failure!");
690 
691     NapiParamUtils::SetValueUInt32(env, audioStreamId, result);
692     return result;
693 }
694 
GetCurrentInputDevices(napi_env env,napi_callback_info info)695 napi_value NapiAudioCapturer::GetCurrentInputDevices(napi_env env, napi_callback_info info)
696 {
697     napi_value result = nullptr;
698     size_t argc = PARAM0;
699 
700     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
701     CHECK_AND_RETURN_RET_LOG(argc == PARAM0,
702         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "invaild param");
703 
704     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
705     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
706 
707     DeviceInfo deviceInfo;
708     int32_t ret = napiAudioCapturer->audioCapturer_->GetCurrentInputDevices(deviceInfo);
709     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetCurrentInputDevices failure!");
710 
711     NapiParamUtils::SetValueDeviceInfo(env, deviceInfo, result);
712     return result;
713 }
714 
GetCurrentAudioCapturerChangeInfo(napi_env env,napi_callback_info info)715 napi_value NapiAudioCapturer::GetCurrentAudioCapturerChangeInfo(napi_env env, napi_callback_info info)
716 {
717     napi_value result = nullptr;
718     size_t argc = PARAM0;
719 
720     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
721     CHECK_AND_RETURN_RET_LOG(argc == PARAM0,
722         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "invaild param");
723 
724     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
725     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
726 
727     AudioCapturerChangeInfo capturerInfo;
728     int32_t ret = napiAudioCapturer->audioCapturer_->GetCurrentCapturerChangeInfo(capturerInfo);
729     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, result, "GetCurrentCapturerChangeInfo failure!");
730 
731     NapiParamUtils::SetAudioCapturerChangeInfoDescriptors(env, capturerInfo, result);
732     return result;
733 }
734 
GetCurrentMicrophones(napi_env env,napi_callback_info info)735 napi_value NapiAudioCapturer::GetCurrentMicrophones(napi_env env, napi_callback_info info)
736 {
737     napi_value result = nullptr;
738     size_t argc = PARAM0;
739 
740     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
741     CHECK_AND_RETURN_RET_LOG(argc == PARAM0,
742         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID), "invaild param");
743 
744     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
745     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
746 
747     vector<sptr<MicrophoneDescriptor>> micDescs;
748     micDescs = napiAudioCapturer->audioCapturer_->GetCurrentMicrophones();
749 
750     NapiParamUtils::SetMicrophoneDescriptors(env, micDescs, result);
751     return result;
752 }
753 
GetState(napi_env env,napi_callback_info info)754 napi_value NapiAudioCapturer::GetState(napi_env env, napi_callback_info info)
755 {
756     napi_value result = nullptr;
757     size_t argc = PARAM0;
758 
759     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
760     if (argc > PARAM0) {
761         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID);
762         napi_get_undefined(env, &result);
763         return result;
764     }
765 
766     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
767     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
768 
769     int32_t capturerState = napiAudioCapturer->audioCapturer_->GetStatus();
770 
771     napi_status status = NapiParamUtils::SetValueInt32(env, capturerState, result);
772     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "SetValueInt32 capturerState fail");
773     return result;
774 }
775 
GetOverflowCount(napi_env env,napi_callback_info info)776 napi_value NapiAudioCapturer::GetOverflowCount(napi_env env, napi_callback_info info)
777 {
778     auto context = std::make_shared<AudioCapturerAsyncContext>();
779     if (context == nullptr) {
780         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
781         return NapiParamUtils::GetUndefinedValue(env);
782     }
783     context->GetCbInfo(env, info);
784 
785     auto executor = [context]() {
786         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
787         auto obj = reinterpret_cast<NapiAudioCapturer*>(context->native);
788         ObjectRefMap objectGuard(obj);
789         auto *napiAudioCapturer = objectGuard.GetPtr();
790         CHECK_AND_RETURN_LOG(CheckAudioCapturerStatus(napiAudioCapturer, context),
791             "context object state is error.");
792         context->overflowCount = napiAudioCapturer->audioCapturer_->GetOverflowCount();
793     };
794 
795     auto complete = [env, context](napi_value &output) {
796         NapiParamUtils::SetValueUInt32(env, context->overflowCount, output);
797     };
798 
799     return NapiAsyncWork::Enqueue(env, context, "GetOverflowCount", executor, complete);
800 }
801 
GetOverflowCountSync(napi_env env,napi_callback_info info)802 napi_value NapiAudioCapturer::GetOverflowCountSync(napi_env env, napi_callback_info info)
803 {
804     napi_value result = nullptr;
805     size_t argc = PARAM0;
806 
807     auto *napiAudioCapturer = GetParamWithSync(env, info, argc, nullptr);
808 
809     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer != nullptr, result, "napiAudioCapturer is nullptr");
810     CHECK_AND_RETURN_RET_LOG(napiAudioCapturer->audioCapturer_ != nullptr, result, "audioCapturer_ is nullptr");
811 
812     uint32_t overflowCount = napiAudioCapturer->audioCapturer_->GetOverflowCount();
813 
814     NapiParamUtils::SetValueUInt32(env, overflowCount, result);
815     return result;
816 }
817 
On(napi_env env,napi_callback_info info)818 napi_value NapiAudioCapturer::On(napi_env env, napi_callback_info info)
819 {
820     const size_t requireArgc = ARGS_TWO;
821     size_t argc = ARGS_THREE;
822 
823     napi_value argv[requireArgc + PARAM1] = {nullptr, nullptr, nullptr};
824     napi_value jsThis = nullptr;
825     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
826     CHECK_AND_RETURN_RET_LOG(status == napi_ok, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM),
827         "napi_get_cb_info failed");
828     CHECK_AND_RETURN_RET_LOG(argc >= requireArgc, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
829         "mandatory parameters are left unspecified"), "argc requeset failed");
830 
831     napi_valuetype eventType = napi_undefined;
832     napi_typeof(env, argv[PARAM0], &eventType);
833     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
834         "incorrect parameter types: The type of eventType must be string"), "eventType invaild");
835 
836     std::string callbackName = NapiParamUtils::GetStringArgument(env, argv[PARAM0]);
837     AUDIO_DEBUG_LOG("NapiAudioCapturer: On callbackName: %{public}s", callbackName.c_str());
838 
839     napi_valuetype handler = napi_undefined;
840     if (argc == requireArgc) {
841         napi_typeof(env, argv[PARAM1], &handler);
842         CHECK_AND_RETURN_RET_LOG(handler == napi_function,
843             NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
844             "incorrect parameter types: The type of callback must be function"), "handler invaild");
845     } else {
846         napi_valuetype paramArg1 = napi_undefined;
847         napi_typeof(env, argv[PARAM1], &paramArg1);
848         napi_valuetype expectedValType = napi_number;  // Default. Reset it with 'callbackName' if check, if required.
849         CHECK_AND_RETURN_RET_LOG(paramArg1 == expectedValType,
850             NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
851             "incorrect parameter types: The type of frame must be number"), "paramArg1 invaild");
852 
853         napi_typeof(env, argv[PARAM2], &handler);
854         CHECK_AND_RETURN_RET_LOG(handler == napi_function,
855             NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
856             "incorrect parameter types: The type of callback must be function"), "handler invaild");
857     }
858 
859     return RegisterCallback(env, jsThis, argv, callbackName);
860 }
861 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * argv,const std::string & cbName)862 napi_value NapiAudioCapturer::RegisterCallback(napi_env env, napi_value jsThis,
863     napi_value *argv, const std::string &cbName)
864 {
865     NapiAudioCapturer *napiCapturer = nullptr;
866     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiCapturer));
867 
868     CHECK_AND_RETURN_RET_LOG(status == napi_ok, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM),
869         "napi_unwrap failed");
870     CHECK_AND_RETURN_RET_LOG(napiCapturer != nullptr, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY),
871         "napiCapturer is nullptr");
872     CHECK_AND_RETURN_RET_LOG(napiCapturer->audioCapturer_ != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
873         NAPI_ERR_NO_MEMORY), "audioCapturer_ is nullptr");
874 
875     napi_value result = nullptr;
876     napi_get_undefined(env, &result);
877 
878     if (!cbName.compare(STATE_CHANGE_CALLBACK_NAME) ||
879         !cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME)) {
880         result = RegisterCapturerCallback(env, argv, cbName, napiCapturer);
881     } else if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
882         result = RegisterPositionCallback(env, argv, cbName, napiCapturer);
883     } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
884         result = RegisterPeriodPositionCallback(env, argv, cbName, napiCapturer);
885     } else if (!cbName.compare(INPUTDEVICE_CHANGE_CALLBACK_NAME)) {
886         RegisterAudioCapturerDeviceChangeCallback(env, argv, napiCapturer);
887     } else if (!cbName.compare(AUDIO_CAPTURER_CHANGE_CALLBACK_NAME)) {
888         RegisterAudioCapturerInfoChangeCallback(env, argv, napiCapturer);
889     } else if (!cbName.compare(READ_DATA_CALLBACK_NAME)) {
890         RegisterCapturerReadDataCallback(env, argv, cbName, napiCapturer);
891     } else {
892         bool unknownCallback = true;
893         CHECK_AND_RETURN_RET_LOG(!unknownCallback, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERROR_INVALID_PARAM,
894             "parameter verification failed: The param of type is not supported"), "audioCapturer_ is nullptr");
895     }
896 
897     return result;
898 }
899 
RegisterCapturerCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioCapturer * napiCapturer)900 napi_value NapiAudioCapturer::RegisterCapturerCallback(napi_env env, napi_value *argv,
901     const std::string &cbName, NapiAudioCapturer *napiCapturer)
902 {
903     CHECK_AND_RETURN_RET_LOG(napiCapturer->callbackNapi_ != nullptr,
904         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY), "napiCapturer is nullptr");
905 
906     std::shared_ptr<NapiAudioCapturerCallback> cb =
907         std::static_pointer_cast<NapiAudioCapturerCallback>(napiCapturer->callbackNapi_);
908     cb->SaveCallbackReference(cbName, argv[PARAM1]);
909 
910     if (!cbName.compare(STATE_CHANGE_CALLBACK_NAME)) {
911         CapturerState state = napiCapturer->audioCapturer_->GetStatus();
912         if (state == CAPTURER_PREPARED) {
913             napiCapturer->callbackNapi_->OnStateChange(state);
914         }
915     }
916 
917     napi_value result = nullptr;
918     napi_get_undefined(env, &result);
919     return result;
920 }
921 
RegisterPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioCapturer * napiCapturer)922 napi_value NapiAudioCapturer::RegisterPositionCallback(napi_env env, napi_value *argv,
923     const std::string &cbName, NapiAudioCapturer *napiCapturer)
924 {
925     int64_t markPosition = 0;
926     NapiParamUtils::GetValueInt64(env, markPosition, argv[PARAM1]);
927 
928     if (markPosition > 0) {
929         napiCapturer->positionCbNapi_ = std::make_shared<NapiCapturerPositionCallback>(env);
930         CHECK_AND_RETURN_RET_LOG(napiCapturer->positionCbNapi_ != nullptr,
931             NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY), "positionCbNapi_ is nullptr");
932         int32_t ret = napiCapturer->audioCapturer_->SetCapturerPositionCallback(markPosition,
933             napiCapturer->positionCbNapi_);
934         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS,
935             NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM), "SetCapturerPositionCallback failed");
936 
937         std::shared_ptr<NapiCapturerPositionCallback> cb =
938             std::static_pointer_cast<NapiCapturerPositionCallback>(napiCapturer->positionCbNapi_);
939         cb->SaveCallbackReference(cbName, argv[PARAM2]);
940     } else {
941         AUDIO_ERR_LOG("NapiAudioCapturer: Mark Position value not supported!!");
942         CHECK_AND_RETURN_RET_LOG(false, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
943             "parameter verification failed: The param of frame is not supported"), "invailed callback");
944     }
945 
946     napi_value result = nullptr;
947     napi_get_undefined(env, &result);
948     return result;
949 }
950 
RegisterPeriodPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioCapturer * napiCapturer)951 napi_value NapiAudioCapturer::RegisterPeriodPositionCallback(napi_env env, napi_value *argv, const std::string &cbName,
952     NapiAudioCapturer *napiCapturer)
953 {
954     int64_t frameCount = 0;
955     napi_get_value_int64(env, argv[PARAM1], &frameCount);
956 
957     if (frameCount > 0) {
958         if (napiCapturer->periodPositionCbNapi_ == nullptr) {
959             napiCapturer->periodPositionCbNapi_ = std::make_shared<NapiCapturerPeriodPositionCallback>(env);
960             CHECK_AND_RETURN_RET_LOG(napiCapturer->periodPositionCbNapi_ != nullptr,
961                 NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY), "periodPositionCbNapi_ is nullptr");
962 
963             int32_t ret = napiCapturer->audioCapturer_->SetCapturerPeriodPositionCallback(frameCount,
964                 napiCapturer->periodPositionCbNapi_);
965             CHECK_AND_RETURN_RET_LOG(ret == SUCCESS,
966                 NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM), "SetCapturerPeriodPositionCallback failed");
967 
968             std::shared_ptr<NapiCapturerPeriodPositionCallback> cb =
969                 std::static_pointer_cast<NapiCapturerPeriodPositionCallback>(napiCapturer->periodPositionCbNapi_);
970             cb->SaveCallbackReference(cbName, argv[PARAM2]);
971         } else {
972             CHECK_AND_RETURN_RET_LOG(false,
973                 NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_ILLEGAL_STATE), "periodReach already subscribed.");
974         }
975     } else {
976         CHECK_AND_RETURN_RET_LOG(false, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
977             "parameter verification failed: The param of frame is not supported"), "frameCount value not supported!");
978     }
979 
980     napi_value result = nullptr;
981     napi_get_undefined(env, &result);
982     return result;
983 }
984 
GetDeviceChangeNapiCallback(napi_value argv,NapiAudioCapturer * napiCapturer)985 std::shared_ptr<NapiAudioCapturerDeviceChangeCallback> NapiAudioCapturer::GetDeviceChangeNapiCallback(napi_value argv,
986     NapiAudioCapturer *napiCapturer)
987 {
988     std::shared_ptr<NapiAudioCapturerDeviceChangeCallback> cb = nullptr;
989     for (auto &iter : napiCapturer->deviceChangeCallbacks_) {
990         if (iter->ContainSameJsCallback(argv)) {
991             cb = iter;
992         }
993     }
994     return cb;
995 }
996 
RegisterAudioCapturerDeviceChangeCallback(napi_env env,napi_value * argv,NapiAudioCapturer * napiCapturer)997 void NapiAudioCapturer::RegisterAudioCapturerDeviceChangeCallback(napi_env env, napi_value *argv,
998     NapiAudioCapturer *napiCapturer)
999 {
1000     CHECK_AND_RETURN_LOG(GetDeviceChangeNapiCallback(argv[PARAM1], napiCapturer) == nullptr,
1001         "Do not register same capturer device callback!");
1002 
1003     std::shared_ptr<NapiAudioCapturerDeviceChangeCallback> cb =
1004         std::make_shared<NapiAudioCapturerDeviceChangeCallback>(env);
1005     CHECK_AND_RETURN_LOG(cb != nullptr, "Memory allocation failed!!");
1006 
1007     cb->SaveCallbackReference(argv[PARAM1]);
1008     int32_t ret =
1009         napiCapturer->audioCapturer_->SetAudioCapturerDeviceChangeCallback(cb);
1010     CHECK_AND_RETURN_LOG(ret == SUCCESS, "Registering of capturer device change callback failed");
1011 
1012     napiCapturer->deviceChangeCallbacks_.push_back(cb);
1013 
1014     AUDIO_DEBUG_LOG("RegisterAudioCapturerDeviceChangeCallback is successful");
1015 }
1016 
GetCapturerInfoChangeNapiCallback(napi_value argv,NapiAudioCapturer * napiCapturer)1017 std::shared_ptr<NapiAudioCapturerInfoChangeCallback> NapiAudioCapturer::GetCapturerInfoChangeNapiCallback(
1018     napi_value argv, NapiAudioCapturer *napiCapturer)
1019 {
1020     std::shared_ptr<NapiAudioCapturerInfoChangeCallback> cb = nullptr;
1021     for (auto &iter : napiCapturer->capturerInfoChangeCallbacks_) {
1022         if (iter->ContainSameJsCallback(argv)) {
1023             cb = iter;
1024         }
1025     }
1026     return cb;
1027 }
1028 
RegisterAudioCapturerInfoChangeCallback(napi_env env,napi_value * argv,NapiAudioCapturer * napiCapturer)1029 void NapiAudioCapturer::RegisterAudioCapturerInfoChangeCallback(napi_env env, napi_value *argv,
1030     NapiAudioCapturer *napiCapturer)
1031 {
1032     CHECK_AND_RETURN_LOG(GetCapturerInfoChangeNapiCallback(argv[PARAM1], napiCapturer) == nullptr,
1033         "Do not register same capturer info change callback!");
1034 
1035     std::shared_ptr<NapiAudioCapturerInfoChangeCallback> cb =
1036         std::make_shared<NapiAudioCapturerInfoChangeCallback>(env);
1037     CHECK_AND_RETURN_LOG(cb != nullptr, "Memory allocation failed!!");
1038 
1039     cb->SaveCallbackReference(argv[PARAM1]);
1040     int32_t ret =
1041         napiCapturer->audioCapturer_->SetAudioCapturerInfoChangeCallback(cb);
1042     CHECK_AND_RETURN_LOG(ret == SUCCESS, "Registering of capturer info change callback failed");
1043 
1044     napiCapturer->capturerInfoChangeCallbacks_.push_back(cb);
1045 
1046     AUDIO_DEBUG_LOG("RegisterAudioCapturerInfoChangeCallback is successful");
1047 }
1048 
RegisterCapturerReadDataCallback(napi_env env,napi_value * argv,const std::string & cbName,NapiAudioCapturer * napiCapturer)1049 void NapiAudioCapturer::RegisterCapturerReadDataCallback(napi_env env, napi_value *argv, const std::string &cbName,
1050     NapiAudioCapturer *napiCapturer)
1051 {
1052     CHECK_AND_RETURN_LOG(napiCapturer->capturerReadDataCallbackNapi_ == nullptr, "readData already subscribed.");
1053 
1054     napiCapturer->capturerReadDataCallbackNapi_ = std::make_shared<NapiCapturerReadDataCallback>(env, napiCapturer);
1055     napiCapturer->audioCapturer_->SetCaptureMode(CAPTURE_MODE_CALLBACK);
1056     CHECK_AND_RETURN_LOG(napiCapturer->capturerReadDataCallbackNapi_ != nullptr, "readDataNapi_ is nullptr");
1057     int32_t ret = napiCapturer->audioCapturer_->SetCapturerReadCallback(napiCapturer->capturerReadDataCallbackNapi_);
1058     CHECK_AND_RETURN_LOG(ret == SUCCESS, "SetCapturerCallback failed");
1059     std::shared_ptr<NapiCapturerReadDataCallback> cb =
1060         std::static_pointer_cast<NapiCapturerReadDataCallback>(napiCapturer->capturerReadDataCallbackNapi_);
1061     cb->AddCallbackReference(cbName, argv[PARAM1]);
1062 
1063     AUDIO_INFO_LOG("Register Callback is successful");
1064 }
1065 
Off(napi_env env,napi_callback_info info)1066 napi_value NapiAudioCapturer::Off(napi_env env, napi_callback_info info)
1067 {
1068     const size_t minArgCount = ARGS_ONE;
1069     size_t argc = ARGS_TWO;
1070 
1071     napi_value argv[minArgCount + 1] = {nullptr, nullptr};
1072     napi_value jsThis = nullptr;
1073     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
1074     CHECK_AND_RETURN_RET_LOG(status == napi_ok, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM),
1075         "napi_get_cb_info failed");
1076     CHECK_AND_RETURN_RET_LOG(argc >= minArgCount, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
1077         "mandatory parameters are left unspecified"), "argc invaild");
1078 
1079     napi_valuetype eventType = napi_undefined;
1080     napi_typeof(env, argv[PARAM0], &eventType);
1081     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
1082         "incorrect parameter types: The type of eventType must be string"), "eventType invaild");
1083 
1084     std::string callbackName = NapiParamUtils::GetStringArgument(env, argv[PARAM0]);
1085     AUDIO_DEBUG_LOG("NapiAudioCapturer: Off callbackName: %{public}s", callbackName.c_str());
1086 
1087     return UnregisterCallback(env, jsThis, argc, argv, callbackName);
1088 }
1089 
UnregisterCallback(napi_env env,napi_value jsThis,size_t argc,napi_value * argv,const std::string & cbName)1090 napi_value NapiAudioCapturer::UnregisterCallback(napi_env env, napi_value jsThis, size_t argc, napi_value *argv,
1091     const std::string &cbName)
1092 {
1093     NapiAudioCapturer *napiCapturer = nullptr;
1094     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiCapturer));
1095     CHECK_AND_RETURN_RET_LOG(status == napi_ok, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM),
1096         "napi_unwrap failed");
1097     CHECK_AND_RETURN_RET_LOG(napiCapturer != nullptr, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY),
1098         "napiCapturer is nullptr");
1099     CHECK_AND_RETURN_RET_LOG(napiCapturer->audioCapturer_ != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
1100         NAPI_ERR_NO_MEMORY), "audioCapturer_ is nullptr");
1101 
1102     if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
1103         napiCapturer->audioCapturer_->UnsetCapturerPositionCallback();
1104         napiCapturer->positionCbNapi_ = nullptr;
1105     } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
1106         napiCapturer->audioCapturer_->UnsetCapturerPeriodPositionCallback();
1107         napiCapturer->periodPositionCbNapi_ = nullptr;
1108     } else if (!cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME)) {
1109         UnregisterCapturerCallback(env, cbName, napiCapturer);
1110     } else if (!cbName.compare(INPUTDEVICE_CHANGE_CALLBACK_NAME)) {
1111         UnregisterAudioCapturerDeviceChangeCallback(env, argc, argv, napiCapturer);
1112     } else if (!cbName.compare(AUDIO_CAPTURER_CHANGE_CALLBACK_NAME)) {
1113         UnregisterAudioCapturerInfoChangeCallback(env, argc, argv, napiCapturer);
1114     } else if (!cbName.compare(READ_DATA_CALLBACK_NAME)) {
1115         UnregisterCapturerReadDataCallback(env, argc, argv, napiCapturer);
1116     } else {
1117         bool unknownCallback = true;
1118         CHECK_AND_RETURN_RET_LOG(!unknownCallback, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
1119             "parameter verification failed: The param of type is not supported"), "NAPI_ERR_UNSUPPORTED cbName");
1120     }
1121 
1122     napi_value result = nullptr;
1123     napi_get_undefined(env, &result);
1124     return result;
1125 }
1126 
UnregisterCapturerCallback(napi_env env,const std::string & cbName,NapiAudioCapturer * napiCapturer)1127 void NapiAudioCapturer::UnregisterCapturerCallback(napi_env env, const std::string &cbName,
1128     NapiAudioCapturer *napiCapturer)
1129 {
1130     CHECK_AND_RETURN_LOG(napiCapturer->callbackNapi_ != nullptr, "capturerCallbackNapi is nullptr");
1131 
1132     std::shared_ptr<NapiAudioCapturerCallback> cb =
1133         std::static_pointer_cast<NapiAudioCapturerCallback>(napiCapturer->callbackNapi_);
1134     cb->RemoveCallbackReference(cbName);
1135 }
1136 
UnregisterAudioCapturerDeviceChangeCallback(napi_env env,size_t argc,napi_value * argv,NapiAudioCapturer * napiCapturer)1137 void NapiAudioCapturer::UnregisterAudioCapturerDeviceChangeCallback(napi_env env, size_t argc,
1138     napi_value *argv, NapiAudioCapturer *napiCapturer)
1139 {
1140     napi_value callback = nullptr;
1141 
1142     if (argc == ARGS_TWO) {
1143         callback = argv[PARAM1];
1144     }
1145 
1146     if (callback != nullptr) {
1147         std::shared_ptr<NapiAudioCapturerDeviceChangeCallback> cb =
1148             GetDeviceChangeNapiCallback(callback, napiCapturer);
1149         CHECK_AND_RETURN_LOG(cb != nullptr, "CapturerCallbackNapi is nullptr");
1150         int32_t ret = napiCapturer->audioCapturer_->RemoveAudioCapturerDeviceChangeCallback(cb);
1151         CHECK_AND_RETURN_LOG(ret == SUCCESS, "Unset of capturer device change callback failed");
1152 
1153         napiCapturer->deviceChangeCallbacks_.remove(cb);
1154         return;
1155     }
1156 
1157     for (auto &iter : napiCapturer->deviceChangeCallbacks_) {
1158         int32_t ret = napiCapturer->audioCapturer_->RemoveAudioCapturerDeviceChangeCallback(iter);
1159         if (ret) {
1160             AUDIO_ERR_LOG("Unset one of capturer device change callback failed!");
1161         }
1162     }
1163     napiCapturer->deviceChangeCallbacks_.clear();
1164     AUDIO_DEBUG_LOG("UnegisterCapturerDeviceChangeCallback is successful");
1165 }
1166 
UnregisterAudioCapturerInfoChangeCallback(napi_env env,size_t argc,napi_value * argv,NapiAudioCapturer * napiCapturer)1167 void NapiAudioCapturer::UnregisterAudioCapturerInfoChangeCallback(napi_env env, size_t argc,
1168     napi_value *argv, NapiAudioCapturer *napiCapturer)
1169 {
1170     napi_value callback = nullptr;
1171 
1172     if (argc == ARGS_TWO) {
1173         callback = argv[PARAM1];
1174     }
1175 
1176     if (callback != nullptr) {
1177         std::shared_ptr<NapiAudioCapturerInfoChangeCallback> cb =
1178             GetCapturerInfoChangeNapiCallback(callback, napiCapturer);
1179         CHECK_AND_RETURN_LOG(cb != nullptr, "CapturerCallbackNapi is nullptr");
1180         int32_t ret = napiCapturer->audioCapturer_->RemoveAudioCapturerInfoChangeCallback(cb);
1181         CHECK_AND_RETURN_LOG(ret == SUCCESS, "Unset of Capturer info change call failed");
1182 
1183         napiCapturer->capturerInfoChangeCallbacks_.remove(cb);
1184         return;
1185     }
1186 
1187     for (auto &iter : napiCapturer->capturerInfoChangeCallbacks_) {
1188         int32_t ret = napiCapturer->audioCapturer_->RemoveAudioCapturerInfoChangeCallback(iter);
1189         if (ret) {
1190             AUDIO_ERR_LOG("Unset one of capturer device change callback failed!");
1191         }
1192     }
1193     napiCapturer->capturerInfoChangeCallbacks_.clear();
1194     AUDIO_DEBUG_LOG("UnregisterAudioCapturerInfoChangeCallback is successful");
1195 }
1196 
UnregisterCapturerReadDataCallback(napi_env env,size_t argc,napi_value * argv,NapiAudioCapturer * napiCapturer)1197 void NapiAudioCapturer::UnregisterCapturerReadDataCallback(napi_env env, size_t argc, napi_value *argv,
1198     NapiAudioCapturer *napiCapturer)
1199 {
1200     napi_value callback = nullptr;
1201 
1202     if (argc == ARGS_TWO) {
1203         callback = argv[PARAM1];
1204     }
1205     CHECK_AND_RETURN_LOG(napiCapturer->capturerReadDataCallbackNapi_ != nullptr,
1206         "napiCapturerReadDataCallback is nullptr, return");
1207 
1208     std::shared_ptr<NapiCapturerReadDataCallback> cb =
1209         std::static_pointer_cast<NapiCapturerReadDataCallback>(napiCapturer->capturerReadDataCallbackNapi_);
1210     cb->RemoveCallbackReference(env, callback);
1211 
1212     AUDIO_INFO_LOG("Unregister Callback is successful");
1213 }
1214 } // namespace AudioStandard
1215 } // namespace OHOS
1216