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