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