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], ¶mArg1);
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