1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "audio_capturer_napi.h"
17 #include "ability.h"
18 #include "audio_capturer_callback_napi.h"
19 #include "audio_errors.h"
20 #include "audio_log.h"
21 #include "audio_manager_napi.h"
22 #include "audio_parameters_napi.h"
23 #include "capturer_period_position_callback_napi.h"
24 #include "capturer_position_callback_napi.h"
25
26 #include "hilog/log.h"
27 #include "napi_base_context.h"
28 #include "securec.h"
29
30 using namespace std;
31 using OHOS::HiviewDFX::HiLog;
32 using OHOS::HiviewDFX::HiLogLabel;
33
34 namespace OHOS {
35 namespace AudioStandard {
36 static __thread napi_ref g_capturerConstructor = nullptr;
37 std::unique_ptr<AudioParameters> AudioCapturerNapi::sAudioParameters_ = nullptr;
38 std::unique_ptr<AudioCapturerOptions> AudioCapturerNapi::sCapturerOptions_ = nullptr;
39 mutex AudioCapturerNapi::createMutex_;
40 int32_t AudioCapturerNapi::isConstructSuccess_ = SUCCESS;
41
42 namespace {
43 constexpr int ARGS_ONE = 1;
44 constexpr int ARGS_TWO = 2;
45 constexpr int ARGS_THREE = 3;
46
47 constexpr int PARAM0 = 0;
48 constexpr int PARAM1 = 1;
49 constexpr int PARAM2 = 2;
50
51 constexpr int TYPE_COMMUNICATION = 7;
52 constexpr int TYPE_VOICE_RECOGNITION = 1;
53 constexpr int TYPE_MIC = 0;
54 constexpr int TYPE_INVALID = -1;
55
56 constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioCapturerNapi"};
57
58 const std::string MARK_REACH_CALLBACK_NAME = "markReach";
59 const std::string PERIOD_REACH_CALLBACK_NAME = "periodReach";
60 #define GET_PARAMS(env, info, num) \
61 size_t argc = num; \
62 napi_value argv[num] = {0}; \
63 napi_value thisVar = nullptr; \
64 void *data; \
65 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)
66 }
67
AudioCapturerNapi()68 AudioCapturerNapi::AudioCapturerNapi()
69 : audioCapturer_(nullptr), contentType_(CONTENT_TYPE_MUSIC), streamUsage_(STREAM_USAGE_MEDIA),
70 deviceRole_(INPUT_DEVICE), deviceType_(DEVICE_TYPE_MIC), sourceType_(SOURCE_TYPE_MIC),
71 capturerFlags_(0), env_(nullptr) {}
72
73 AudioCapturerNapi::~AudioCapturerNapi() = default;
74
Destructor(napi_env env,void * nativeObject,void * finalize_hint)75 void AudioCapturerNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
76 {
77 if (nativeObject != nullptr) {
78 auto obj = static_cast<AudioCapturerNapi *>(nativeObject);
79 delete obj;
80 }
81 }
82
Init(napi_env env,napi_value exports)83 napi_value AudioCapturerNapi::Init(napi_env env, napi_value exports)
84 {
85 napi_status status;
86 napi_value constructor;
87 napi_value result = nullptr;
88 const int32_t refCount = 1;
89 napi_get_undefined(env, &result);
90
91 napi_property_descriptor audio_capturer_properties[] = {
92 DECLARE_NAPI_FUNCTION("getCapturerInfo", GetCapturerInfo),
93 DECLARE_NAPI_FUNCTION("getStreamInfo", GetStreamInfo),
94 DECLARE_NAPI_FUNCTION("start", Start),
95 DECLARE_NAPI_FUNCTION("read", Read),
96 DECLARE_NAPI_FUNCTION("getAudioTime", GetAudioTime),
97 DECLARE_NAPI_FUNCTION("stop", Stop),
98 DECLARE_NAPI_FUNCTION("release", Release),
99 DECLARE_NAPI_FUNCTION("getBufferSize", GetBufferSize),
100 DECLARE_NAPI_FUNCTION("getAudioStreamId", GetAudioStreamId),
101 DECLARE_NAPI_FUNCTION("on", On),
102 DECLARE_NAPI_FUNCTION("off", Off),
103 DECLARE_NAPI_GETTER("state", GetState)
104 };
105
106 napi_property_descriptor static_prop[] = {
107 DECLARE_NAPI_STATIC_FUNCTION("createAudioCapturer", CreateAudioCapturer)
108 };
109
110 status = napi_define_class(env, AUDIO_CAPTURER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
111 sizeof(audio_capturer_properties) / sizeof(audio_capturer_properties[PARAM0]),
112 audio_capturer_properties, &constructor);
113 if (status != napi_ok) {
114 return result;
115 }
116
117 status = napi_create_reference(env, constructor, refCount, &g_capturerConstructor);
118 if (status == napi_ok) {
119 status = napi_set_named_property(env, exports, AUDIO_CAPTURER_NAPI_CLASS_NAME.c_str(), constructor);
120 if (status == napi_ok) {
121 status = napi_define_properties(env, exports,
122 sizeof(static_prop) / sizeof(static_prop[PARAM0]), static_prop);
123 if (status == napi_ok) {
124 return exports;
125 }
126 }
127 }
128
129 HiLog::Error(LABEL, "Failure in AudioCapturerNapi::Init()");
130
131 return result;
132 }
133
AddNamedProperty(napi_env env,napi_value object,const std::string name,int32_t enumValue)134 napi_status AudioCapturerNapi::AddNamedProperty(napi_env env, napi_value object,
135 const std::string name, int32_t enumValue)
136 {
137 napi_status status;
138 napi_value enumNapiValue;
139
140 status = napi_create_int32(env, enumValue, &enumNapiValue);
141 if (status == napi_ok) {
142 status = napi_set_named_property(env, object, name.c_str(), enumNapiValue);
143 }
144
145 return status;
146 }
147
SetValueInt32(const napi_env & env,const std::string & fieldStr,const int intValue,napi_value & result)148 static void SetValueInt32(const napi_env& env, const std::string& fieldStr, const int intValue, napi_value& result)
149 {
150 napi_value value = nullptr;
151 napi_create_int32(env, intValue, &value);
152 napi_set_named_property(env, result, fieldStr.c_str(), value);
153 }
154
GetAbilityContext(napi_env env)155 static shared_ptr<AbilityRuntime::Context> GetAbilityContext(napi_env env)
156 {
157 HiLog::Info(LABEL, "Getting context with FA model");
158 auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
159 if (ability == nullptr) {
160 HiLog::Error(LABEL, "Failed to obtain ability in FA mode");
161 return nullptr;
162 }
163
164 auto faContext = ability->GetAbilityContext();
165 if (faContext == nullptr) {
166 HiLog::Error(LABEL, "GetAbilityContext returned null in FA model");
167 return nullptr;
168 }
169
170 return faContext;
171 }
172
Construct(napi_env env,napi_callback_info info)173 napi_value AudioCapturerNapi::Construct(napi_env env, napi_callback_info info)
174 {
175 napi_status status;
176 napi_value result = nullptr;
177 napi_get_undefined(env, &result);
178
179 GET_PARAMS(env, info, ARGS_TWO);
180
181 unique_ptr<AudioCapturerNapi> capturerNapi = make_unique<AudioCapturerNapi>();
182 CHECK_AND_RETURN_RET_LOG(capturerNapi != nullptr, result, "No memory");
183 capturerNapi->env_ = env;
184 capturerNapi->sourceType_ = sCapturerOptions_->capturerInfo.sourceType;
185 capturerNapi->capturerFlags_ = sCapturerOptions_->capturerInfo.capturerFlags;
186
187 AudioCapturerOptions capturerOptions = {};
188 capturerOptions.streamInfo.samplingRate = sCapturerOptions_->streamInfo.samplingRate;
189 capturerOptions.streamInfo.encoding = sCapturerOptions_->streamInfo.encoding;
190 capturerOptions.streamInfo.format = sCapturerOptions_->streamInfo.format;
191 capturerOptions.streamInfo.channels = sCapturerOptions_->streamInfo.channels;
192
193 capturerOptions.capturerInfo.sourceType = sCapturerOptions_->capturerInfo.sourceType;
194 capturerOptions.capturerInfo.capturerFlags = sCapturerOptions_->capturerInfo.capturerFlags;
195
196 std::shared_ptr<AbilityRuntime::Context> abilityContext = GetAbilityContext(env);
197 std::string cacheDir = "";
198 if (abilityContext != nullptr) {
199 cacheDir = abilityContext->GetCacheDir();
200 } else {
201 cacheDir = "/data/storage/el2/base/haps/entry/files";
202 }
203 capturerNapi->audioCapturer_ = AudioCapturer::Create(capturerOptions, cacheDir);
204
205 if (capturerNapi->audioCapturer_ == nullptr) {
206 HiLog::Error(LABEL, "Capturer Create failed");
207 AudioCapturerNapi::isConstructSuccess_ = NAPI_ERR_SYSTEM;
208 }
209
210 if (capturerNapi->audioCapturer_ != nullptr && capturerNapi->callbackNapi_ == nullptr) {
211 capturerNapi->callbackNapi_ = std::make_shared<AudioCapturerCallbackNapi>(env);
212 CHECK_AND_RETURN_RET_LOG(capturerNapi->callbackNapi_ != nullptr, result, "No memory");
213 int32_t ret = capturerNapi->audioCapturer_->SetCapturerCallback(capturerNapi->callbackNapi_);
214 if (ret) {
215 AUDIO_DEBUG_LOG("AudioCapturerNapi::Construct SetCapturerCallback failed");
216 }
217 }
218
219 status = napi_wrap(env, thisVar, static_cast<void*>(capturerNapi.get()),
220 AudioCapturerNapi::Destructor, nullptr, nullptr);
221 if (status == napi_ok) {
222 capturerNapi.release();
223 return thisVar;
224 }
225
226 HiLog::Error(LABEL, "Failed in AudioCapturerNapi::Construct()!");
227 return result;
228 }
229
CreateAudioCapturer(napi_env env,napi_callback_info info)230 napi_value AudioCapturerNapi::CreateAudioCapturer(napi_env env, napi_callback_info info)
231 {
232 HiLog::Info(LABEL, "%{public}s IN", __func__);
233 napi_status status;
234 napi_value result = nullptr;
235 bool inputRight = true;
236
237 GET_PARAMS(env, info, ARGS_TWO);
238 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
239
240 if (asyncContext == nullptr) {
241 return result;
242 }
243
244 if (argc < ARGS_ONE) {
245 asyncContext->status = NAPI_ERR_INVALID_PARAM;
246 }
247
248 for (size_t i = PARAM0; i < argc; i++) {
249 napi_valuetype valueType = napi_undefined;
250 napi_typeof(env, argv[i], &valueType);
251 if (i == PARAM0 && valueType == napi_object) {
252 if (ParseCapturerOptions(env, argv[i], &(asyncContext->capturerOptions)) == false) {
253 HiLog::Error(LABEL, "Parsing of capturer options failed");
254 inputRight = false;
255 }
256 } else if (i == PARAM1) {
257 if (valueType == napi_function) {
258 napi_create_reference(env, argv[i], REFERENCE_CREATION_COUNT, &asyncContext->callbackRef);
259 }
260 break;
261 } else {
262 asyncContext->status = NAPI_ERR_INVALID_PARAM;
263 }
264 }
265
266 if (asyncContext->callbackRef == nullptr) {
267 napi_create_promise(env, &asyncContext->deferred, &result);
268 } else {
269 napi_get_undefined(env, &result);
270 }
271
272 napi_value resource = nullptr;
273 napi_create_string_utf8(env, "CreateAudioCapturer", NAPI_AUTO_LENGTH, &resource);
274
275 if (inputRight == false){
276 status = napi_create_async_work(
277 env, nullptr, resource,
278 [](napi_env env, void *data) {
279 auto context = static_cast<AudioCapturerAsyncContext *>(data);
280 context->status = NAPI_ERR_INVALID_PARAM;
281 HiLog::Error(LABEL, "ParseCapturerOptions fail, invalid param!");
282 },
283 CheckCapturerAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
284 } else {
285 status = napi_create_async_work(
286 env, nullptr, resource,
287 [](napi_env env, void *data) {
288 auto context = static_cast<AudioCapturerAsyncContext *>(data);
289 context->status = SUCCESS;
290 },
291 GetCapturerAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
292 }
293
294 if (status != napi_ok) {
295 result = nullptr;
296 } else {
297 status = napi_queue_async_work(env, asyncContext->work);
298 if (status == napi_ok) {
299 asyncContext.release();
300 } else {
301 result = nullptr;
302 }
303 }
304
305 return result;
306 }
307
CommonCallbackRoutine(napi_env env,AudioCapturerAsyncContext * & asyncContext,const napi_value & valueParam)308 void AudioCapturerNapi::CommonCallbackRoutine(napi_env env, AudioCapturerAsyncContext* &asyncContext,
309 const napi_value &valueParam)
310 {
311 napi_value result[ARGS_TWO] = {0};
312 napi_value retVal;
313
314 if (!asyncContext->status) {
315 napi_get_undefined(env, &result[PARAM0]);
316 result[PARAM1] = valueParam;
317 } else {
318 napi_value message = nullptr;
319 std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
320 napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
321
322 napi_value code = nullptr;
323 napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
324
325 napi_create_error(env, code, message, &result[PARAM0]);
326 napi_get_undefined(env, &result[PARAM1]);
327 }
328
329 if (asyncContext->deferred) {
330 if (!asyncContext->status) {
331 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
332 } else {
333 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
334 }
335 } else {
336 napi_value callback = nullptr;
337 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
338 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
339 napi_delete_reference(env, asyncContext->callbackRef);
340 }
341 napi_delete_async_work(env, asyncContext->work);
342
343 delete asyncContext;
344 asyncContext = nullptr;
345 }
346
GetCapturerAsyncCallbackComplete(napi_env env,napi_status status,void * data)347 void AudioCapturerNapi::GetCapturerAsyncCallbackComplete(napi_env env, napi_status status, void *data)
348 {
349 napi_value valueParam = nullptr;
350 auto asyncContext = static_cast<AudioCapturerAsyncContext *>(data);
351
352 if (asyncContext != nullptr) {
353 if (!asyncContext->status) {
354 unique_ptr<AudioCapturerOptions> capturerOptions = make_unique<AudioCapturerOptions>();
355 capturerOptions->streamInfo.samplingRate = asyncContext->capturerOptions.streamInfo.samplingRate;
356 capturerOptions->streamInfo.encoding = asyncContext->capturerOptions.streamInfo.encoding;
357 capturerOptions->streamInfo.format = asyncContext->capturerOptions.streamInfo.format;
358 capturerOptions->streamInfo.channels = asyncContext->capturerOptions.streamInfo.channels;
359 capturerOptions->capturerInfo.sourceType = asyncContext->capturerOptions.capturerInfo.sourceType;
360 capturerOptions->capturerInfo.capturerFlags = asyncContext->capturerOptions.capturerInfo.capturerFlags;
361
362 valueParam = CreateAudioCapturerWrapper(env, capturerOptions);
363 asyncContext->status = AudioCapturerNapi::isConstructSuccess_;
364 AudioCapturerNapi::isConstructSuccess_ = SUCCESS;
365 }
366 CommonCallbackRoutine(env, asyncContext, valueParam);
367 } else {
368 HiLog::Error(LABEL, "ERROR: GetCapturerAsyncCallbackComplete is Null!");
369 }
370 }
371
CheckCapturerAsyncCallbackComplete(napi_env env,napi_status status,void * data)372 void AudioCapturerNapi::CheckCapturerAsyncCallbackComplete(napi_env env, napi_status status, void *data)
373 {
374 napi_value valueParam = nullptr;
375 auto asyncContext = static_cast<AudioCapturerAsyncContext *>(data);
376 if (asyncContext != nullptr) {
377 CommonCallbackRoutine(env, asyncContext, valueParam);
378 } else {
379 HiLog::Error(LABEL, "ERROR: CheckCapturerAsyncCallbackComplete is Null!");
380 }
381 }
382
SetFunctionAsyncCallbackComplete(napi_env env,napi_status status,void * data)383 void AudioCapturerNapi::SetFunctionAsyncCallbackComplete(napi_env env, napi_status status, void *data)
384 {
385 auto asyncContext = static_cast<AudioCapturerAsyncContext*>(data);
386 napi_value valueParam = nullptr;
387
388 if (asyncContext != nullptr) {
389 if (!asyncContext->status) {
390 napi_get_undefined(env, &valueParam);
391 }
392 CommonCallbackRoutine(env, asyncContext, valueParam);
393 } else {
394 HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
395 }
396 }
397
AudioCapturerInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)398 void AudioCapturerNapi::AudioCapturerInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
399 {
400 auto asyncContext = static_cast<AudioCapturerAsyncContext *>(data);
401 napi_value valueParam = nullptr;
402
403 if (asyncContext != nullptr) {
404 if (!asyncContext->status) {
405 (void)napi_create_object(env, &valueParam);
406 SetValueInt32(env, "source", static_cast<int32_t>(asyncContext->sourceType), valueParam);
407 SetValueInt32(env, "capturerFlags", static_cast<int32_t>(asyncContext->capturerFlags), valueParam);
408 }
409 CommonCallbackRoutine(env, asyncContext, valueParam);
410 } else {
411 HiLog::Error(LABEL, "ERROR: AudioCapturerInfoAsyncCallbackComplete* is Null!");
412 }
413 }
414
AudioStreamInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)415 void AudioCapturerNapi::AudioStreamInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
416 {
417 auto asyncContext = static_cast<AudioCapturerAsyncContext *>(data);
418 napi_value valueParam = nullptr;
419
420 if (asyncContext != nullptr) {
421 if (!asyncContext->status) {
422 (void)napi_create_object(env, &valueParam);
423 SetValueInt32(env, "samplingRate", static_cast<int32_t>(asyncContext->samplingRate), valueParam);
424 SetValueInt32(env, "channels", static_cast<int32_t>(asyncContext->audioChannel), valueParam);
425 SetValueInt32(env, "sampleFormat", static_cast<int32_t>(asyncContext->audioSampleFormat), valueParam);
426 SetValueInt32(env, "encodingType", static_cast<int32_t>(asyncContext->audioEncoding), valueParam);
427 }
428 CommonCallbackRoutine(env, asyncContext, valueParam);
429 } else {
430 HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
431 }
432 }
433
ReadAsyncCallbackComplete(napi_env env,napi_status status,void * data)434 void AudioCapturerNapi::ReadAsyncCallbackComplete(napi_env env, napi_status status, void *data)
435 {
436 auto asyncContext = static_cast<AudioCapturerAsyncContext *>(data);
437 napi_value valueParam = nullptr;
438
439 if (asyncContext != nullptr) {
440 if (!asyncContext->status) {
441 uint8_t *native = nullptr;
442 napi_create_arraybuffer(env, asyncContext->bytesRead, reinterpret_cast<void **>(&native), &valueParam);
443 if (memcpy_s(native, asyncContext->bytesRead, asyncContext->buffer, asyncContext->bytesRead)) {
444 valueParam = nullptr;
445 }
446
447 free(asyncContext->buffer);
448 }
449 CommonCallbackRoutine(env, asyncContext, valueParam);
450 } else {
451 HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
452 }
453 }
454
VoidAsyncCallbackComplete(napi_env env,napi_status status,void * data)455 void AudioCapturerNapi::VoidAsyncCallbackComplete(napi_env env, napi_status status, void *data)
456 {
457 auto asyncContext = static_cast<AudioCapturerAsyncContext*>(data);
458 napi_value valueParam = nullptr;
459
460 if (asyncContext != nullptr) {
461 if (!asyncContext->status) {
462 napi_get_undefined(env, &valueParam);
463 }
464 CommonCallbackRoutine(env, asyncContext, valueParam);
465 } else {
466 HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
467 }
468 }
469
IsTrueAsyncCallbackComplete(napi_env env,napi_status status,void * data)470 void AudioCapturerNapi::IsTrueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
471 {
472 auto asyncContext = static_cast<AudioCapturerAsyncContext*>(data);
473 napi_value valueParam = nullptr;
474
475 if (asyncContext != nullptr) {
476 if (!asyncContext->status) {
477 napi_get_boolean(env, asyncContext->isTrue, &valueParam);
478 }
479 CommonCallbackRoutine(env, asyncContext, valueParam);
480 } else {
481 HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
482 }
483 }
484
GetBufferSizeAsyncCallbackComplete(napi_env env,napi_status status,void * data)485 void AudioCapturerNapi::GetBufferSizeAsyncCallbackComplete(napi_env env, napi_status status, void *data)
486 {
487 auto asyncContext = static_cast<AudioCapturerAsyncContext*>(data);
488 napi_value valueParam = nullptr;
489
490 if (asyncContext != nullptr) {
491 if (!asyncContext->status) {
492 napi_create_uint32(env, asyncContext->bufferSize, &valueParam);
493 }
494 CommonCallbackRoutine(env, asyncContext, valueParam);
495 } else {
496 HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
497 }
498 }
499
GetAudioStreamIdCallbackComplete(napi_env env,napi_status status,void * data)500 void AudioCapturerNapi::GetAudioStreamIdCallbackComplete(napi_env env, napi_status status, void *data)
501 {
502 auto asyncContext = static_cast<AudioCapturerAsyncContext *>(data);
503 napi_value valueParam = nullptr;
504
505 if (asyncContext != nullptr) {
506 if (!asyncContext->status) {
507 napi_create_uint32(env, asyncContext->audioStreamId, &valueParam);
508 }
509 CommonCallbackRoutine(env, asyncContext, valueParam);
510 } else {
511 HiLog::Error(LABEL, "ERROR::GetAudioStreamIdCallbackComplete* is Null!");
512 }
513 }
514
GetIntValueAsyncCallbackComplete(napi_env env,napi_status status,void * data)515 void AudioCapturerNapi::GetIntValueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
516 {
517 auto asyncContext = static_cast<AudioCapturerAsyncContext*>(data);
518 napi_value valueParam = nullptr;
519
520 if (asyncContext != nullptr) {
521 if (!asyncContext->status) {
522 napi_create_int32(env, asyncContext->intValue, &valueParam);
523 }
524 CommonCallbackRoutine(env, asyncContext, valueParam);
525 } else {
526 HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
527 }
528 }
529
GetInt64ValueAsyncCallbackComplete(napi_env env,napi_status status,void * data)530 void AudioCapturerNapi::GetInt64ValueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
531 {
532 auto asyncContext = static_cast<AudioCapturerAsyncContext*>(data);
533 napi_value valueParam = nullptr;
534
535 if (asyncContext != nullptr) {
536 if (!asyncContext->status) {
537 napi_create_int64(env, asyncContext->time, &valueParam);
538 }
539 CommonCallbackRoutine(env, asyncContext, valueParam);
540 } else {
541 HiLog::Error(LABEL, "ERROR: AudioCapturerAsyncContext* is Null!");
542 }
543 }
544
GetCapturerInfo(napi_env env,napi_callback_info info)545 napi_value AudioCapturerNapi::GetCapturerInfo(napi_env env, napi_callback_info info)
546 {
547 HiLog::Info(LABEL, "%{public}s IN", __func__);
548 napi_status status;
549 const int32_t refCount = 1;
550 napi_value result = nullptr;
551
552 GET_PARAMS(env, info, ARGS_ONE);
553
554 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
555 THROW_ERROR_ASSERT(env, asyncContext != nullptr, NAPI_ERR_NO_MEMORY);
556 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
557 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
558 if (argc > PARAM0) {
559 napi_valuetype valueType = napi_undefined;
560 napi_typeof(env, argv[PARAM0], &valueType);
561 if (valueType == napi_function) {
562 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
563 }
564 }
565
566 if (asyncContext->callbackRef == nullptr) {
567 napi_create_promise(env, &asyncContext->deferred, &result);
568 } else {
569 napi_get_undefined(env, &result);
570 }
571
572 napi_value resource = nullptr;
573 napi_create_string_utf8(env, "GetCapturerInfo", NAPI_AUTO_LENGTH, &resource);
574
575 status = napi_create_async_work(
576 env, nullptr, resource,
577 [](napi_env env, void *data) {
578 auto context = static_cast<AudioCapturerAsyncContext *>(data);
579 AudioCapturerInfo capturerInfo = {};
580 context->status = context->objectInfo->audioCapturer_->GetCapturerInfo(capturerInfo);
581 if (context->status == SUCCESS) {
582 context->sourceType = capturerInfo.sourceType;
583 context->capturerFlags = capturerInfo.capturerFlags;
584 }
585 },
586 AudioCapturerInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
587 if (status != napi_ok) {
588 result = nullptr;
589 } else {
590 status = napi_queue_async_work(env, asyncContext->work);
591 if (status == napi_ok) {
592 asyncContext.release();
593 } else {
594 result = nullptr;
595 }
596 }
597 }
598
599 return result;
600 }
601
GetStreamInfo(napi_env env,napi_callback_info info)602 napi_value AudioCapturerNapi::GetStreamInfo(napi_env env, napi_callback_info info)
603 {
604 napi_status status;
605 const int32_t refCount = 1;
606 napi_value result = nullptr;
607
608 GET_PARAMS(env, info, ARGS_ONE);
609
610 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
611 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
612 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
613 if (argc > PARAM0) {
614 napi_valuetype valueType = napi_undefined;
615 napi_typeof(env, argv[PARAM0], &valueType);
616 if (valueType == napi_function) {
617 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
618 }
619 }
620
621 if (asyncContext->callbackRef == nullptr) {
622 napi_create_promise(env, &asyncContext->deferred, &result);
623 } else {
624 napi_get_undefined(env, &result);
625 }
626
627 napi_value resource = nullptr;
628 napi_create_string_utf8(env, "GetStreamInfo", NAPI_AUTO_LENGTH, &resource);
629 status = napi_create_async_work(
630 env, nullptr, resource,
631 [](napi_env env, void *data) {
632 auto context = static_cast<AudioCapturerAsyncContext *>(data);
633
634 AudioStreamInfo streamInfo;
635 context->status = context->objectInfo->audioCapturer_->GetStreamInfo(streamInfo);
636 if (context->status == SUCCESS) {
637 context->audioSampleFormat = static_cast<AudioSampleFormat>(streamInfo.format);
638 context->samplingRate = streamInfo.samplingRate;
639 context->audioChannel = streamInfo.channels;
640 context->audioEncoding = streamInfo.encoding;
641 }
642 },
643 AudioStreamInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
644 if (status != napi_ok) {
645 result = nullptr;
646 } else {
647 status = napi_queue_async_work(env, asyncContext->work);
648 if (status == napi_ok) {
649 asyncContext.release();
650 } else {
651 result = nullptr;
652 }
653 }
654 }
655
656 return result;
657 }
658
GetAudioStreamId(napi_env env,napi_callback_info info)659 napi_value AudioCapturerNapi::GetAudioStreamId(napi_env env, napi_callback_info info)
660 {
661 napi_status status;
662 const int32_t refCount = 1;
663 napi_value result = nullptr;
664
665 GET_PARAMS(env, info, ARGS_ONE);
666
667 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
668 THROW_ERROR_ASSERT(env, asyncContext != nullptr, NAPI_ERR_NO_MEMORY);
669
670 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
671 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
672 if (argc > PARAM0) {
673 napi_valuetype valueType = napi_undefined;
674 napi_typeof(env, argv[PARAM0], &valueType);
675 if (valueType == napi_function) {
676 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
677 }
678 }
679
680 if (asyncContext->callbackRef == nullptr) {
681 napi_create_promise(env, &asyncContext->deferred, &result);
682 } else {
683 napi_get_undefined(env, &result);
684 }
685
686 napi_value resource = nullptr;
687 napi_create_string_utf8(env, "GetAudioStreamId", NAPI_AUTO_LENGTH, &resource);
688 status = napi_create_async_work(
689 env, nullptr, resource,
690 [](napi_env env, void *data) {
691 auto context = static_cast<AudioCapturerAsyncContext *>(data);
692 int32_t streamIdStatus;
693 streamIdStatus = context->objectInfo->audioCapturer_->
694 GetAudioStreamId(context->audioStreamId);
695 if (streamIdStatus == ERR_ILLEGAL_STATE) {
696 context->status = NAPI_ERR_ILLEGAL_STATE;
697 } else if (streamIdStatus == ERR_INVALID_INDEX) {
698 context->status = NAPI_ERR_SYSTEM;
699 } else {
700 context->status = SUCCESS;
701 }
702 },
703 GetAudioStreamIdCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
704 if (status != napi_ok) {
705 result = nullptr;
706 } else {
707 status = napi_queue_async_work(env, asyncContext->work);
708 if (status == napi_ok) {
709 asyncContext.release();
710 } else {
711 result = nullptr;
712 }
713 }
714 }
715 return result;
716 }
717
Start(napi_env env,napi_callback_info info)718 napi_value AudioCapturerNapi::Start(napi_env env, napi_callback_info info)
719 {
720 napi_status status;
721 const int32_t refCount = 1;
722 napi_value result = nullptr;
723
724 GET_PARAMS(env, info, ARGS_ONE);
725
726 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
727 THROW_ERROR_ASSERT(env, asyncContext != nullptr, NAPI_ERR_NO_MEMORY);
728
729 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
730 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
731 if (argc > PARAM0) {
732 napi_valuetype valueType = napi_undefined;
733 napi_typeof(env, argv[PARAM0], &valueType);
734 if (valueType == napi_function) {
735 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
736 }
737 }
738
739 if (asyncContext->callbackRef == nullptr) {
740 napi_create_promise(env, &asyncContext->deferred, &result);
741 } else {
742 napi_get_undefined(env, &result);
743 }
744
745 napi_value resource = nullptr;
746 napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
747
748 status = napi_create_async_work(
749 env, nullptr, resource,
750 [](napi_env env, void *data) {
751 auto context = static_cast<AudioCapturerAsyncContext *>(data);
752 context->isTrue = context->objectInfo->audioCapturer_->Start();
753 if (context->isTrue) {
754 context->status = SUCCESS;
755 } else {
756 context->status = NAPI_ERR_SYSTEM;
757 }
758 },
759 VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
760 if (status != napi_ok) {
761 result = nullptr;
762 } else {
763 status = napi_queue_async_work(env, asyncContext->work);
764 if (status == napi_ok) {
765 asyncContext.release();
766 } else {
767 result = nullptr;
768 }
769 }
770 }
771
772 return result;
773 }
774
Read(napi_env env,napi_callback_info info)775 napi_value AudioCapturerNapi::Read(napi_env env, napi_callback_info info)
776 {
777 napi_status status;
778 const int32_t refCount = 1;
779 napi_value result = nullptr;
780
781 GET_PARAMS(env, info, ARGS_THREE);
782
783 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
784 if (argc < ARGS_TWO) {
785 asyncContext->status = NAPI_ERR_INVALID_PARAM;
786 }
787
788 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
789 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
790 for (size_t i = PARAM0; i < argc; i++) {
791 napi_valuetype valueType = napi_undefined;
792 napi_typeof(env, argv[i], &valueType);
793
794 if ((i == PARAM0) && (valueType == napi_number)) {
795 napi_get_value_uint32(env, argv[i], &asyncContext->userSize);
796 } else if ((i == PARAM1) && (valueType == napi_boolean)) {
797 napi_get_value_bool(env, argv[i], &asyncContext->isBlocking);
798 } else if (i == PARAM2) {
799 if (valueType == napi_function) {
800 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
801 }
802 break;
803 } else {
804 asyncContext->status = NAPI_ERR_INVALID_PARAM;
805 }
806 }
807
808 if (asyncContext->callbackRef == nullptr) {
809 napi_create_promise(env, &asyncContext->deferred, &result);
810 } else {
811 napi_get_undefined(env, &result);
812 }
813
814 napi_value resource = nullptr;
815 napi_create_string_utf8(env, "Read", NAPI_AUTO_LENGTH, &resource);
816
817 status = napi_create_async_work(
818 env, nullptr, resource,
819 [](napi_env env, void *data) {
820 auto context = static_cast<AudioCapturerAsyncContext *>(data);
821 if (context->status == SUCCESS) {
822 context->status = NAPI_ERR_SYSTEM;
823 uint32_t userSize = context->userSize;
824 auto buffer = std::make_unique<uint8_t[]>(userSize);
825 if (!buffer) {
826 return;
827 }
828
829 size_t bytesRead = 0;
830 while (bytesRead < context->userSize) {
831 int32_t len = context->objectInfo->audioCapturer_->Read(*(buffer.get() + bytesRead),
832 userSize - bytesRead,
833 context->isBlocking);
834 if (len >= 0) {
835 bytesRead += len;
836 } else {
837 bytesRead = len;
838 break;
839 }
840 }
841
842 if (bytesRead > 0) {
843 context->bytesRead = bytesRead;
844 context->buffer = buffer.get();
845 buffer.release();
846 context->status = SUCCESS;
847 }
848 }
849 },
850 ReadAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
851 if (status != napi_ok) {
852 result = nullptr;
853 } else {
854 status = napi_queue_async_work(env, asyncContext->work);
855 if (status == napi_ok) {
856 asyncContext.release();
857 } else {
858 result = nullptr;
859 }
860 }
861 }
862
863 return result;
864 }
865
GetAudioTime(napi_env env,napi_callback_info info)866 napi_value AudioCapturerNapi::GetAudioTime(napi_env env, napi_callback_info info)
867 {
868 napi_status status;
869 const int32_t refCount = 1;
870 napi_value result = nullptr;
871
872 GET_PARAMS(env, info, ARGS_ONE);
873
874 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
875
876 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
877 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
878 if (argc > PARAM0) {
879 napi_valuetype valueType = napi_undefined;
880 napi_typeof(env, argv[PARAM0], &valueType);
881 if (valueType == napi_function) {
882 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
883 }
884 }
885
886 if (asyncContext->callbackRef == nullptr) {
887 napi_create_promise(env, &asyncContext->deferred, &result);
888 } else {
889 napi_get_undefined(env, &result);
890 }
891
892 napi_value resource = nullptr;
893 napi_create_string_utf8(env, "GetAudioTime", NAPI_AUTO_LENGTH, &resource);
894
895 status = napi_create_async_work(
896 env, nullptr, resource,
897 [](napi_env env, void *data) {
898 auto context = static_cast<AudioCapturerAsyncContext *>(data);
899 context->status = NAPI_ERR_SYSTEM;
900 Timestamp timestamp;
901 if (context->objectInfo->audioCapturer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC)) {
902 const uint64_t secToNanosecond = 1000000000;
903 context->time = timestamp.time.tv_nsec + timestamp.time.tv_sec * secToNanosecond;
904 context->status = SUCCESS;
905 }
906 },
907 GetInt64ValueAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
908 if (status != napi_ok) {
909 result = nullptr;
910 } else {
911 status = napi_queue_async_work(env, asyncContext->work);
912 if (status == napi_ok) {
913 asyncContext.release();
914 } else {
915 result = nullptr;
916 }
917 }
918 }
919
920 return result;
921 }
922
Stop(napi_env env,napi_callback_info info)923 napi_value AudioCapturerNapi::Stop(napi_env env, napi_callback_info info)
924 {
925 napi_status status;
926 const int32_t refCount = 1;
927 napi_value result = nullptr;
928
929 GET_PARAMS(env, info, ARGS_ONE);
930
931 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
932
933 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
934 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
935 if (argc > PARAM0) {
936 napi_valuetype valueType = napi_undefined;
937 napi_typeof(env, argv[PARAM0], &valueType);
938 if (valueType == napi_function) {
939 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
940 }
941 }
942
943 if (asyncContext->callbackRef == nullptr) {
944 napi_create_promise(env, &asyncContext->deferred, &result);
945 } else {
946 napi_get_undefined(env, &result);
947 }
948
949 napi_value resource = nullptr;
950 napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
951
952 status = napi_create_async_work(
953 env, nullptr, resource,
954 [](napi_env env, void *data) {
955 auto context = static_cast<AudioCapturerAsyncContext *>(data);
956 context->isTrue = context->objectInfo->audioCapturer_->Stop();
957 if (context->isTrue) {
958 context->status = SUCCESS;
959 } else {
960 context->status = NAPI_ERR_SYSTEM;
961 }
962 },
963 VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
964 if (status != napi_ok) {
965 result = nullptr;
966 } else {
967 status = napi_queue_async_work(env, asyncContext->work);
968 if (status == napi_ok) {
969 asyncContext.release();
970 } else {
971 result = nullptr;
972 }
973 }
974 }
975
976 return result;
977 }
978
Release(napi_env env,napi_callback_info info)979 napi_value AudioCapturerNapi::Release(napi_env env, napi_callback_info info)
980 {
981 napi_status status;
982 const int32_t refCount = 1;
983 napi_value result = nullptr;
984
985 GET_PARAMS(env, info, ARGS_ONE);
986
987 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
988
989 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
990 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
991 if (argc > PARAM0) {
992 napi_valuetype valueType = napi_undefined;
993 napi_typeof(env, argv[PARAM0], &valueType);
994 if (valueType == napi_function) {
995 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
996 }
997 }
998
999 if (asyncContext->callbackRef == nullptr) {
1000 napi_create_promise(env, &asyncContext->deferred, &result);
1001 } else {
1002 napi_get_undefined(env, &result);
1003 }
1004
1005 napi_value resource = nullptr;
1006 napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
1007
1008 status = napi_create_async_work(
1009 env, nullptr, resource,
1010 [](napi_env env, void *data) {
1011 auto context = static_cast<AudioCapturerAsyncContext *>(data);
1012 context->isTrue = context->objectInfo->audioCapturer_->Release();
1013 if (context->isTrue) {
1014 context->status = SUCCESS;
1015 } else {
1016 context->status = NAPI_ERR_SYSTEM;
1017 }
1018 },
1019 VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1020 if (status != napi_ok) {
1021 result = nullptr;
1022 } else {
1023 status = napi_queue_async_work(env, asyncContext->work);
1024 if (status == napi_ok) {
1025 asyncContext.release();
1026 } else {
1027 result = nullptr;
1028 }
1029 }
1030 }
1031
1032 return result;
1033 }
1034
RegisterPeriodPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioCapturerNapi * capturerNapi)1035 napi_value AudioCapturerNapi::RegisterPeriodPositionCallback(napi_env env, napi_value* argv, const std::string& cbName,
1036 AudioCapturerNapi *capturerNapi)
1037 {
1038 int64_t frameCount = 0;
1039 napi_get_value_int64(env, argv[PARAM1], &frameCount);
1040
1041 if (frameCount > 0) {
1042 if (capturerNapi->periodPositionCBNapi_ == nullptr) {
1043 capturerNapi->periodPositionCBNapi_ = std::make_shared<CapturerPeriodPositionCallbackNapi>(env);
1044 THROW_ERROR_ASSERT(env, capturerNapi->periodPositionCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1045
1046 int32_t ret = capturerNapi->audioCapturer_->SetCapturerPeriodPositionCallback(frameCount,
1047 capturerNapi->periodPositionCBNapi_);
1048 THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
1049
1050 std::shared_ptr<CapturerPeriodPositionCallbackNapi> cb =
1051 std::static_pointer_cast<CapturerPeriodPositionCallbackNapi>(capturerNapi->periodPositionCBNapi_);
1052 cb->SaveCallbackReference(cbName, argv[PARAM2]);
1053 } else {
1054 AUDIO_DEBUG_LOG("AudioCapturerNapi: periodReach already subscribed.");
1055 THROW_ERROR_ASSERT(env, false, NAPI_ERR_ILLEGAL_STATE);
1056 }
1057 } else {
1058 AUDIO_ERR_LOG("AudioCapturerNapi: frameCount value not supported!");
1059 THROW_ERROR_ASSERT(env, false, NAPI_ERR_INPUT_INVALID);
1060 }
1061
1062 napi_value result = nullptr;
1063 napi_get_undefined(env, &result);
1064 return result;
1065 }
1066
RegisterPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioCapturerNapi * capturerNapi)1067 napi_value AudioCapturerNapi::RegisterPositionCallback(napi_env env, napi_value* argv,
1068 const std::string& cbName, AudioCapturerNapi *capturerNapi)
1069 {
1070 int64_t markPosition = 0;
1071 napi_get_value_int64(env, argv[PARAM1], &markPosition);
1072
1073 if (markPosition > 0) {
1074 capturerNapi->positionCBNapi_ = std::make_shared<CapturerPositionCallbackNapi>(env);
1075 THROW_ERROR_ASSERT(env, capturerNapi->positionCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1076 int32_t ret = capturerNapi->audioCapturer_->SetCapturerPositionCallback(markPosition,
1077 capturerNapi->positionCBNapi_);
1078 THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
1079
1080 std::shared_ptr<CapturerPositionCallbackNapi> cb =
1081 std::static_pointer_cast<CapturerPositionCallbackNapi>(capturerNapi->positionCBNapi_);
1082 cb->SaveCallbackReference(cbName, argv[PARAM2]);
1083 } else {
1084 AUDIO_ERR_LOG("AudioCapturerNapi: Mark Position value not supported!!");
1085 THROW_ERROR_ASSERT(env, false, NAPI_ERR_INPUT_INVALID);
1086 }
1087
1088 napi_value result = nullptr;
1089 napi_get_undefined(env, &result);
1090 return result;
1091 }
1092
RegisterCapturerCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioCapturerNapi * capturerNapi)1093 napi_value AudioCapturerNapi::RegisterCapturerCallback(napi_env env, napi_value* argv,
1094 const std::string& cbName, AudioCapturerNapi *capturerNapi)
1095 {
1096 THROW_ERROR_ASSERT(env, capturerNapi->callbackNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1097
1098 std::shared_ptr<AudioCapturerCallbackNapi> cb =
1099 std::static_pointer_cast<AudioCapturerCallbackNapi>(capturerNapi->callbackNapi_);
1100 cb->SaveCallbackReference(cbName, argv[PARAM1]);
1101
1102 if (!cbName.compare(STATE_CHANGE_CALLBACK_NAME)) {
1103 CapturerState state = capturerNapi->audioCapturer_->GetStatus();
1104 if (state == CAPTURER_PREPARED) {
1105 capturerNapi->callbackNapi_->OnStateChange(state);
1106 }
1107 }
1108
1109 napi_value result = nullptr;
1110 napi_get_undefined(env, &result);
1111 return result;
1112 }
1113
RegisterCallback(napi_env env,napi_value jsThis,napi_value * argv,const std::string & cbName)1114 napi_value AudioCapturerNapi::RegisterCallback(napi_env env, napi_value jsThis,
1115 napi_value* argv, const std::string& cbName)
1116 {
1117 AudioCapturerNapi *capturerNapi = nullptr;
1118 napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&capturerNapi));
1119 THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
1120 THROW_ERROR_ASSERT(env, capturerNapi != nullptr, NAPI_ERR_NO_MEMORY);
1121 THROW_ERROR_ASSERT(env, capturerNapi->audioCapturer_ != nullptr, NAPI_ERR_NO_MEMORY);
1122
1123 napi_value result = nullptr;
1124 napi_get_undefined(env, &result);
1125
1126 if (!cbName.compare(STATE_CHANGE_CALLBACK_NAME)) {
1127 result = RegisterCapturerCallback(env, argv, cbName, capturerNapi);
1128 } else if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
1129 result = RegisterPositionCallback(env, argv, cbName, capturerNapi);
1130 } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
1131 result = RegisterPeriodPositionCallback(env, argv, cbName, capturerNapi);
1132 } else {
1133 bool unknownCallback = true;
1134 THROW_ERROR_ASSERT(env, !unknownCallback, NAPI_ERROR_INVALID_PARAM);
1135 }
1136
1137 return result;
1138 }
1139
On(napi_env env,napi_callback_info info)1140 napi_value AudioCapturerNapi::On(napi_env env, napi_callback_info info)
1141 {
1142 const size_t requireArgc = 2;
1143 size_t argc = 3;
1144
1145 napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
1146 napi_value jsThis = nullptr;
1147 napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
1148 THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
1149 THROW_ERROR_ASSERT(env, argc >= requireArgc, NAPI_ERR_INPUT_INVALID);
1150
1151 napi_valuetype eventType = napi_undefined;
1152 napi_typeof(env, argv[0], &eventType);
1153 THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INPUT_INVALID);
1154
1155 std::string callbackName = AudioCommonNapi::GetStringArgument(env, argv[0]);
1156 AUDIO_DEBUG_LOG("AudioCapturerNapi: On callbackName: %{public}s", callbackName.c_str());
1157
1158 napi_valuetype handler = napi_undefined;
1159 if (argc == requireArgc) {
1160 napi_typeof(env, argv[1], &handler);
1161 THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
1162 } else {
1163 napi_valuetype paramArg1 = napi_undefined;
1164 napi_typeof(env, argv[1], ¶mArg1);
1165 napi_valuetype expectedValType = napi_number; // Default. Reset it with 'callbackName' if check, if required.
1166 THROW_ERROR_ASSERT(env, paramArg1 == expectedValType, NAPI_ERR_INPUT_INVALID);
1167
1168 const int32_t arg2 = 2;
1169 napi_typeof(env, argv[arg2], &handler);
1170 THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
1171 }
1172
1173 return RegisterCallback(env, jsThis, argv, callbackName);
1174 }
1175
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & cbName)1176 napi_value AudioCapturerNapi::UnregisterCallback(napi_env env, napi_value jsThis, const std::string& cbName)
1177 {
1178 AudioCapturerNapi *capturerNapi = nullptr;
1179 napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&capturerNapi));
1180 THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
1181 THROW_ERROR_ASSERT(env, capturerNapi != nullptr, NAPI_ERR_NO_MEMORY);
1182 THROW_ERROR_ASSERT(env, capturerNapi->audioCapturer_ != nullptr, NAPI_ERR_NO_MEMORY);
1183
1184 if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
1185 capturerNapi->audioCapturer_->UnsetCapturerPositionCallback();
1186 capturerNapi->positionCBNapi_ = nullptr;
1187 } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
1188 capturerNapi->audioCapturer_->UnsetCapturerPeriodPositionCallback();
1189 capturerNapi->periodPositionCBNapi_ = nullptr;
1190 } else {
1191 bool unknownCallback = true;
1192 THROW_ERROR_ASSERT(env, !unknownCallback, NAPI_ERR_UNSUPPORTED);
1193 }
1194
1195 napi_value result = nullptr;
1196 napi_get_undefined(env, &result);
1197 return result;
1198 }
1199
Off(napi_env env,napi_callback_info info)1200 napi_value AudioCapturerNapi::Off(napi_env env, napi_callback_info info)
1201 {
1202 const size_t requireArgc = 1;
1203 size_t argc = 1;
1204
1205 napi_value argv[requireArgc] = {nullptr};
1206 napi_value jsThis = nullptr;
1207 napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
1208 THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
1209 THROW_ERROR_ASSERT(env, argc >= requireArgc, NAPI_ERR_INVALID_PARAM);
1210
1211 napi_valuetype eventType = napi_undefined;
1212 napi_typeof(env, argv[0], &eventType);
1213 THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INVALID_PARAM);
1214
1215 std::string callbackName = AudioCommonNapi::GetStringArgument(env, argv[0]);
1216 AUDIO_DEBUG_LOG("AudioCapturerNapi: Off callbackName: %{public}s", callbackName.c_str());
1217
1218 return UnregisterCallback(env, jsThis, callbackName);
1219 }
1220
GetBufferSize(napi_env env,napi_callback_info info)1221 napi_value AudioCapturerNapi::GetBufferSize(napi_env env, napi_callback_info info)
1222 {
1223 napi_status status;
1224 const int32_t refCount = 1;
1225 napi_value result = nullptr;
1226
1227 GET_PARAMS(env, info, ARGS_ONE);
1228
1229 unique_ptr<AudioCapturerAsyncContext> asyncContext = make_unique<AudioCapturerAsyncContext>();
1230
1231 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1232 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1233 if (argc > PARAM0) {
1234 napi_valuetype valueType = napi_undefined;
1235 napi_typeof(env, argv[PARAM0], &valueType);
1236 if (valueType == napi_function) {
1237 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1238 }
1239 }
1240
1241 if (asyncContext->callbackRef == nullptr) {
1242 napi_create_promise(env, &asyncContext->deferred, &result);
1243 } else {
1244 napi_get_undefined(env, &result);
1245 }
1246
1247 napi_value resource = nullptr;
1248 napi_create_string_utf8(env, "GetBufferSize", NAPI_AUTO_LENGTH, &resource);
1249
1250 status = napi_create_async_work(
1251 env, nullptr, resource,
1252 [](napi_env env, void *data) {
1253 auto context = static_cast<AudioCapturerAsyncContext *>(data);
1254 size_t bufferSize;
1255 context->status = context->objectInfo->audioCapturer_->GetBufferSize(bufferSize);
1256 if (context->status == SUCCESS) {
1257 context->bufferSize = bufferSize;
1258 }
1259 },
1260 GetBufferSizeAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1261 if (status != napi_ok) {
1262 result = nullptr;
1263 } else {
1264 status = napi_queue_async_work(env, asyncContext->work);
1265 if (status == napi_ok) {
1266 asyncContext.release();
1267 } else {
1268 result = nullptr;
1269 }
1270 }
1271 }
1272
1273 return result;
1274 }
1275
GetState(napi_env env,napi_callback_info info)1276 napi_value AudioCapturerNapi::GetState(napi_env env, napi_callback_info info)
1277 {
1278 napi_value jsThis = nullptr;
1279 napi_value undefinedResult = nullptr;
1280 napi_get_undefined(env, &undefinedResult);
1281
1282 size_t argCount = 0;
1283 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1284 if (status != napi_ok || jsThis == nullptr) {
1285 HiLog::Error(LABEL, "Failed to retrieve details about the callback");
1286 return undefinedResult;
1287 }
1288
1289 AudioCapturerNapi *capturerNapi = nullptr;
1290 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&capturerNapi));
1291 if (status != napi_ok || capturerNapi == nullptr) {
1292 HiLog::Error(LABEL, "Failed to get instance");
1293 return undefinedResult;
1294 }
1295
1296 if (capturerNapi->audioCapturer_ == nullptr) {
1297 HiLog::Error(LABEL, "No memory");
1298 return undefinedResult;
1299 }
1300
1301 int32_t capturerState = capturerNapi->audioCapturer_->GetStatus();
1302
1303 napi_value jsResult = nullptr;
1304 status = napi_create_int32(env, capturerState, &jsResult);
1305 if (status != napi_ok) {
1306 HiLog::Error(LABEL, "napi_create_int32 error");
1307 return undefinedResult;
1308 }
1309
1310 HiLog::Info(LABEL, "AudioCapturerNapi: GetState Complete, Current state: %{public}d", capturerState);
1311 return jsResult;
1312 }
1313
ParseCapturerOptions(napi_env env,napi_value root,AudioCapturerOptions * opts)1314 bool AudioCapturerNapi::ParseCapturerOptions(napi_env env, napi_value root, AudioCapturerOptions *opts)
1315 {
1316 napi_value res = nullptr;
1317 bool result = false;
1318
1319 if (napi_get_named_property(env, root, "streamInfo", &res) == napi_ok) {
1320 result = ParseStreamInfo(env, res, &(opts->streamInfo));
1321 }
1322
1323 if (result == false) {
1324 return result;
1325 }
1326
1327 if (napi_get_named_property(env, root, "capturerInfo", &res) == napi_ok) {
1328 result = ParseCapturerInfo(env, res, &(opts->capturerInfo));
1329 }
1330
1331 return result;
1332 }
1333
ParseCapturerInfo(napi_env env,napi_value root,AudioCapturerInfo * capturerInfo)1334 bool AudioCapturerNapi::ParseCapturerInfo(napi_env env, napi_value root, AudioCapturerInfo *capturerInfo)
1335 {
1336 napi_value tempValue = nullptr;
1337 int32_t intValue = {0};
1338
1339 if (napi_get_named_property(env, root, "source", &tempValue) == napi_ok) {
1340 napi_get_value_int32(env, tempValue, &intValue);
1341 switch (intValue) {
1342 case TYPE_INVALID:
1343 case TYPE_MIC:
1344 case TYPE_VOICE_RECOGNITION:
1345 case TYPE_COMMUNICATION:
1346 capturerInfo->sourceType = static_cast<SourceType>(intValue);
1347 break;
1348 default:
1349 HiLog::Error(LABEL, "Unknown SourceType: %{public}d", intValue);
1350 return false;
1351 }
1352 }
1353
1354 if (napi_get_named_property(env, root, "capturerFlags", &tempValue) == napi_ok) {
1355 napi_get_value_int32(env, tempValue, &(capturerInfo->capturerFlags));
1356 }
1357
1358 return true;
1359 }
1360
ParseStreamInfo(napi_env env,napi_value root,AudioStreamInfo * streamInfo)1361 bool AudioCapturerNapi::ParseStreamInfo(napi_env env, napi_value root, AudioStreamInfo* streamInfo)
1362 {
1363 napi_value tempValue = nullptr;
1364 int32_t intValue = {0};
1365
1366 if (napi_get_named_property(env, root, "samplingRate", &tempValue) == napi_ok) {
1367 napi_get_value_int32(env, tempValue, &intValue);
1368 if (intValue >= SAMPLE_RATE_8000 && intValue <= SAMPLE_RATE_96000) {
1369 streamInfo->samplingRate = static_cast<AudioSamplingRate>(intValue);
1370 } else {
1371 HiLog::Error(LABEL, "Unknown AudioSamplingRate: %{public}d", intValue);
1372 return false;
1373 }
1374 }
1375
1376 if (napi_get_named_property(env, root, "channels", &tempValue) == napi_ok) {
1377 napi_get_value_int32(env, tempValue, &intValue);
1378 streamInfo->channels = static_cast<AudioChannel>(intValue);
1379 }
1380
1381 if (napi_get_named_property(env, root, "sampleFormat", &tempValue) == napi_ok) {
1382 napi_get_value_int32(env, tempValue, &intValue);
1383 streamInfo->format = static_cast<OHOS::AudioStandard::AudioSampleFormat>(intValue);
1384 }
1385
1386 if (napi_get_named_property(env, root, "encodingType", &tempValue) == napi_ok) {
1387 napi_get_value_int32(env, tempValue, &intValue);
1388 streamInfo->encoding = static_cast<AudioEncodingType>(intValue);
1389 }
1390
1391 return true;
1392 }
1393
CreateAudioCapturerWrapper(napi_env env,unique_ptr<AudioCapturerOptions> & captureOptions)1394 napi_value AudioCapturerNapi::CreateAudioCapturerWrapper(napi_env env, unique_ptr<AudioCapturerOptions> &captureOptions)
1395 {
1396 lock_guard<mutex> lock(createMutex_);
1397 napi_status status;
1398 napi_value result = nullptr;
1399 napi_value constructor;
1400
1401 if (captureOptions != nullptr) {
1402 status = napi_get_reference_value(env, g_capturerConstructor, &constructor);
1403 if (status == napi_ok) {
1404 sCapturerOptions_ = move(captureOptions);
1405 status = napi_new_instance(env, constructor, 0, nullptr, &result);
1406 sCapturerOptions_.release();
1407 if (status == napi_ok) {
1408 return result;
1409 }
1410 }
1411 HiLog::Error(LABEL, "Failed in CreateAudioCapturerWrapper, %{public}d", status);
1412 }
1413
1414 napi_get_undefined(env, &result);
1415
1416 return result;
1417 }
1418 } // namespace AudioStandard
1419 } // namespace OHOS
1420