• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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], &paramArg1);
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