1 /*
2  * Copyright (C) 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 "avrecorder_callback.h"
17 #include <uv.h>
18 #include "media_errors.h"
19 #include "scope_guard.h"
20 #include "media_log.h"
21 #ifdef SUPPORT_RECORDER_CREATE_FILE
22 #include "media_library_comm_napi.h"
23 #endif
24 
25 namespace {
26     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_RECORDER, "AVRecorderCallback"};
27 }
28 
29 namespace OHOS {
30 namespace Media {
31 #ifdef SUPPORT_RECORDER_CREATE_FILE
32 const int32_t CAMERA_SHOT_TYPE = 1; // CameraShotType VIDEO
33 #endif
AVRecorderCallback(napi_env env)34 AVRecorderCallback::AVRecorderCallback(napi_env env) : env_(env)
35 {
36     MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances create", FAKE_POINTER(this));
37 }
38 
~AVRecorderCallback()39 AVRecorderCallback::~AVRecorderCallback()
40 {
41     MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances destroy", FAKE_POINTER(this));
42 }
43 
SaveCallbackReference(const std::string & name,std::weak_ptr<AutoRef> ref)44 void AVRecorderCallback::SaveCallbackReference(const std::string &name, std::weak_ptr<AutoRef> ref)
45 {
46     std::lock_guard<std::mutex> lock(mutex_);
47     refMap_[name] = ref;
48     MEDIA_LOGI("Set callback type: %{public}s", name.c_str());
49 }
50 
CancelCallbackReference(const std::string & name)51 void AVRecorderCallback::CancelCallbackReference(const std::string &name)
52 {
53     std::lock_guard<std::mutex> lock(mutex_);
54     auto iter = refMap_.find(name);
55     if (iter != refMap_.end()) {
56         refMap_.erase(iter);
57     }
58     MEDIA_LOGI("Cancel callback type: %{public}s", name.c_str());
59 }
60 
ClearCallbackReference()61 void AVRecorderCallback::ClearCallbackReference()
62 {
63     std::lock_guard<std::mutex> lock(mutex_);
64     refMap_.clear();
65     MEDIA_LOGI("ClearCallback!");
66 }
67 
SendErrorCallback(int32_t errCode,const std::string & msg)68 void AVRecorderCallback::SendErrorCallback(int32_t errCode, const std::string &msg)
69 {
70     std::lock_guard<std::mutex> lock(mutex_);
71     if (refMap_.find(AVRecorderEvent::EVENT_ERROR) == refMap_.end()) {
72         MEDIA_LOGW("can not find error callback!");
73         return;
74     }
75 
76     AVRecordJsCallback *cb = new(std::nothrow) AVRecordJsCallback();
77     CHECK_AND_RETURN_LOG(cb != nullptr, "cb is nullptr");
78     cb->autoRef = refMap_.at(AVRecorderEvent::EVENT_ERROR);
79     cb->callbackName = AVRecorderEvent::EVENT_ERROR;
80     cb->errorCode = errCode;
81     cb->errorMsg = msg;
82     return OnJsErrorCallBack(cb);
83 }
84 
SendStateCallback(const std::string & state,const StateChangeReason & reason)85 void AVRecorderCallback::SendStateCallback(const std::string &state, const StateChangeReason &reason)
86 {
87     std::lock_guard<std::mutex> lock(mutex_);
88     currentState_ = state;
89     if (refMap_.find(AVRecorderEvent::EVENT_STATE_CHANGE) == refMap_.end()) {
90         MEDIA_LOGW("can not find statechange callback!");
91         return;
92     }
93 
94     AVRecordJsCallback *cb = new(std::nothrow) AVRecordJsCallback();
95     CHECK_AND_RETURN_LOG(cb != nullptr, "cb is nullptr");
96     cb->autoRef = refMap_.at(AVRecorderEvent::EVENT_STATE_CHANGE);
97     cb->callbackName = AVRecorderEvent::EVENT_STATE_CHANGE;
98     cb->reason = reason;
99     cb->state = state;
100     return OnJsStateCallBack(cb);
101 }
102 
SendAudioCaptureChangeCallback(const AudioRecorderChangeInfo & audioRecorderChangeInfo)103 void AVRecorderCallback::SendAudioCaptureChangeCallback(const AudioRecorderChangeInfo &audioRecorderChangeInfo)
104 {
105     std::lock_guard<std::mutex> lock(mutex_);
106     if (refMap_.find(AVRecorderEvent::EVENT_AUDIO_CAPTURE_CHANGE) == refMap_.end()) {
107         MEDIA_LOGW("can not find audioCaptureChange callback");
108         return;
109     }
110 
111     AVRecordJsCallback *cb = new(std::nothrow) AVRecordJsCallback();
112     CHECK_AND_RETURN_LOG(cb != nullptr, "cb is nullptr");
113     cb->autoRef = refMap_.at(AVRecorderEvent::EVENT_AUDIO_CAPTURE_CHANGE);
114     cb->callbackName = AVRecorderEvent::EVENT_AUDIO_CAPTURE_CHANGE;
115     cb->audioRecorderChangeInfo = audioRecorderChangeInfo;
116     return OnJsAudioCaptureChangeCallback(cb);
117 }
118 
SendPhotoAssertAvailableCallback(const std::string & uri)119 void AVRecorderCallback::SendPhotoAssertAvailableCallback(const std::string &uri)
120 {
121     std::lock_guard<std::mutex> lock(mutex_);
122     if (refMap_.find(AVRecorderEvent::EVENT_PHOTO_ASSET_AVAILABLE) == refMap_.end()) {
123         MEDIA_LOGW("can not find PhotoAssertAvailable callback");
124         return;
125     }
126 
127     AVRecordJsCallback *cb = new(std::nothrow) AVRecordJsCallback();
128     CHECK_AND_RETURN_LOG(cb != nullptr, "cb is nullptr");
129     cb->autoRef = refMap_.at(AVRecorderEvent::EVENT_PHOTO_ASSET_AVAILABLE);
130     cb->callbackName = AVRecorderEvent::EVENT_PHOTO_ASSET_AVAILABLE;
131     cb->uri = uri;
132 #ifdef SUPPORT_RECORDER_CREATE_FILE
133     return OnJsPhotoAssertAvailableCallback(cb);
134 #endif
135 }
136 
GetState()137 std::string AVRecorderCallback::GetState()
138 {
139     std::lock_guard<std::mutex> lock(mutex_);
140     return currentState_;
141 }
142 
OnError(RecorderErrorType errorType,int32_t errCode)143 void AVRecorderCallback::OnError(RecorderErrorType errorType, int32_t errCode)
144 {
145     MEDIA_LOGI("OnError is called, name: %{public}d, error message: %{public}d", errorType, errCode);
146     if (errCode == MSERR_DATA_SOURCE_IO_ERROR) {
147         SendErrorCallback(MSERR_EXT_API9_TIMEOUT,
148             "The video input stream timed out. Please confirm that the input stream is normal.");
149     } else if (errCode == MSERR_DATA_SOURCE_OBTAIN_MEM_ERROR) {
150         SendErrorCallback(MSERR_EXT_API9_TIMEOUT,
151             "Read data from audio timeout, please confirm whether the audio module is normal.");
152     } else if (errCode == MSERR_DATA_SOURCE_ERROR_UNKNOWN) {
153         SendErrorCallback(MSERR_EXT_API9_IO, "Video input data is abnormal."
154             " Please confirm that the pts, width, height, size and other data are normal.");
155     } else if (errCode == MSERR_AUD_INTERRUPT) {
156         SendErrorCallback(MSERR_EXT_API9_AUDIO_INTERRUPTED,
157             "Record failed by audio interrupt.");
158     } else {
159         SendErrorCallback(MSERR_EXT_API9_IO, "IO error happened.");
160     }
161     SendStateCallback(AVRecorderState::STATE_ERROR, StateChangeReason::BACKGROUND);
162 }
163 
OnInfo(int32_t type,int32_t extra)164 void AVRecorderCallback::OnInfo(int32_t type, int32_t extra)
165 {
166     MEDIA_LOGI("OnInfo() is called, type: %{public}d, extra: %{public}d", type, extra);
167 }
168 
OnAudioCaptureChange(const AudioRecorderChangeInfo & audioRecorderChangeInfo)169 void AVRecorderCallback::OnAudioCaptureChange(const AudioRecorderChangeInfo &audioRecorderChangeInfo)
170 {
171     MEDIA_LOGI("OnAudioCaptureChange() is called");
172     SendAudioCaptureChangeCallback(audioRecorderChangeInfo);
173 }
174 
OnPhotoAssertAvailable(const std::string & uri)175 void AVRecorderCallback::OnPhotoAssertAvailable(const std::string &uri)
176 {
177     MEDIA_LOGI("OnPhotoAssertAvailable() is called");
178     SendPhotoAssertAvailableCallback(uri);
179 }
180 
OnJsStateCallBack(AVRecordJsCallback * jsCb) const181 void AVRecorderCallback::OnJsStateCallBack(AVRecordJsCallback *jsCb) const
182 {
183     ON_SCOPE_EXIT(0) {
184         delete jsCb;
185     };
186 
187     uv_loop_s *loop = nullptr;
188     napi_get_uv_event_loop(env_, &loop);
189     CHECK_AND_RETURN_LOG(loop != nullptr, "Fail to get uv event loop");
190 
191     uv_work_t *work = new(std::nothrow) uv_work_t;
192     CHECK_AND_RETURN_LOG(work != nullptr, "fail to new uv_work_t");
193     ON_SCOPE_EXIT(1) {
194         delete work;
195     };
196 
197     work->data = reinterpret_cast<void *>(jsCb);
198     int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
199         // Js Thread
200         CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
201         AVRecordJsCallback *event = reinterpret_cast<AVRecordJsCallback *>(work->data);
202         std::string request = event->callbackName;
203         MEDIA_LOGI("uv_queue_work_with_qos start, state changes to %{public}s", event->state.c_str());
204         do {
205             CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
206             std::shared_ptr<AutoRef> ref = event->autoRef.lock();
207             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
208 
209             napi_handle_scope scope = nullptr;
210             napi_open_handle_scope(ref->env_, &scope);
211             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
212             ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
213 
214             napi_value jsCallback = nullptr;
215             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
216             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
217                 request.c_str());
218 
219             napi_value args[2] = { nullptr };
220             nstatus = napi_create_string_utf8(ref->env_, event->state.c_str(), NAPI_AUTO_LENGTH, &args[0]);
221             CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
222                 "%{public}s fail to create callback", request.c_str());
223 
224             nstatus = napi_create_int32(ref->env_, event->reason, &args[1]);
225             CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[1] != nullptr,
226                 "%{public}s fail to create callback", request.c_str());
227 
228             const size_t argCount = 2;
229             napi_value result = nullptr;
230             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
231             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
232         } while (0);
233         delete event;
234         delete work;
235     }, uv_qos_user_initiated);
236     CHECK_AND_RETURN_LOG(ret == 0, "fail to uv_queue_work_with_qos task");
237 
238     CANCEL_SCOPE_EXIT_GUARD(0);
239     CANCEL_SCOPE_EXIT_GUARD(1);
240 }
241 
242 #ifdef SUPPORT_RECORDER_CREATE_FILE
OnJsPhotoAssertAvailableCallback(AVRecordJsCallback * jsCb) const243 void AVRecorderCallback::OnJsPhotoAssertAvailableCallback(AVRecordJsCallback *jsCb) const
244 {
245     ON_SCOPE_EXIT(0) {
246         delete jsCb;
247     };
248 
249     uv_loop_s *loop = nullptr;
250     napi_get_uv_event_loop(env_, &loop);
251     CHECK_AND_RETURN_LOG(loop != nullptr, "Fail to get uv event loop");
252 
253     uv_work_t *work = new(std::nothrow) uv_work_t;
254     CHECK_AND_RETURN_LOG(work != nullptr, "fail to new uv_work_t");
255     ON_SCOPE_EXIT(1) {
256         delete work;
257     };
258 
259     work->data = reinterpret_cast<void *>(jsCb);
260     int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
261         CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
262         if (work->data == nullptr) {
263             delete work;
264             MEDIA_LOGE("workdata is nullptr");
265             return;
266         }
267         AVRecordJsCallback *event = reinterpret_cast<AVRecordJsCallback *>(work->data);
268         std::string request = event->callbackName;
269         do {
270             CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
271             std::shared_ptr<AutoRef> ref = event->autoRef.lock();
272             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
273 
274             napi_handle_scope scope = nullptr;
275             napi_open_handle_scope(ref->env_, &scope);
276             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
277             ON_SCOPE_EXIT(0) {
278                 napi_close_handle_scope(ref->env_, scope);
279             };
280 
281             napi_value jsCallback = nullptr;
282             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
283             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
284                 request.c_str());
285 
286             const size_t argCount = 1;
287             napi_value args[argCount] = { nullptr };
288 
289             args[0] = Media::MediaLibraryCommNapi::CreatePhotoAssetNapi(ref->env_, event->uri, CAMERA_SHOT_TYPE);
290             napi_value result = nullptr;
291             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
292             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
293         } while (0);
294         delete event;
295         delete work;
296     }, uv_qos_user_initiated);
297     CHECK_AND_RETURN_LOG(ret == 0, "fail to uv_queue_work_with_qos task");
298 
299     CANCEL_SCOPE_EXIT_GUARD(0);
300     CANCEL_SCOPE_EXIT_GUARD(1);
301 }
302 #endif
303 
OnJsAudioCaptureChangeCallback(AVRecordJsCallback * jsCb) const304 void AVRecorderCallback::OnJsAudioCaptureChangeCallback(AVRecordJsCallback *jsCb) const
305 {
306     ON_SCOPE_EXIT(0) {
307         delete jsCb;
308     };
309 
310     uv_loop_s *loop = nullptr;
311     napi_get_uv_event_loop(env_, &loop);
312     CHECK_AND_RETURN_LOG(loop != nullptr, "Fail to get uv event loop");
313 
314     uv_work_t *work = new(std::nothrow) uv_work_t;
315     CHECK_AND_RETURN_LOG(work != nullptr, "fail to new uv_work_t");
316     ON_SCOPE_EXIT(1) {
317         delete work;
318     };
319 
320     work->data = reinterpret_cast<void *>(jsCb);
321     int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
322         // Js Thread
323         CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
324         if (work->data == nullptr) {
325             delete work;
326             MEDIA_LOGE("workdata is nullptr");
327             return;
328         }
329         AVRecordJsCallback *event = reinterpret_cast<AVRecordJsCallback *>(work->data);
330         std::string request = event->callbackName;
331         do {
332             CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
333             std::shared_ptr<AutoRef> ref = event->autoRef.lock();
334             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
335 
336             napi_handle_scope scope = nullptr;
337             napi_open_handle_scope(ref->env_, &scope);
338             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
339             ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
340 
341             napi_value jsCallback = nullptr;
342             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
343             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
344                 request.c_str());
345 
346             const size_t argCount = 1;
347             napi_value args[argCount] = { nullptr };
348             std::shared_ptr<AudioCaptureChangeInfoJsCallback> ChangeInfoJsCallback =
349                 std::make_shared<AudioCaptureChangeInfoJsCallback>(event->audioRecorderChangeInfo);
350             nstatus = ChangeInfoJsCallback->GetJsResult(ref->env_, args[0]);
351             napi_value result = nullptr;
352             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
353             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
354         } while (0);
355         delete event;
356         delete work;
357     }, uv_qos_user_initiated);
358     CHECK_AND_RETURN_LOG(ret == 0, "fail to uv_queue_work_with_qos task");
359 
360     CANCEL_SCOPE_EXIT_GUARD(0);
361     CANCEL_SCOPE_EXIT_GUARD(1);
362 }
363 
OnJsErrorCallBack(AVRecordJsCallback * jsCb) const364 void AVRecorderCallback::OnJsErrorCallBack(AVRecordJsCallback *jsCb) const
365 {
366     ON_SCOPE_EXIT(0) {
367         delete jsCb;
368     };
369 
370     uv_loop_s *loop = nullptr;
371     napi_get_uv_event_loop(env_, &loop);
372     CHECK_AND_RETURN_LOG(loop != nullptr, "Fail to get uv event loop");
373 
374     uv_work_t *work = new(std::nothrow) uv_work_t;
375     CHECK_AND_RETURN_LOG(work != nullptr, "fail to new uv_work_t");
376     ON_SCOPE_EXIT(1) {
377         delete work;
378     };
379 
380     work->data = reinterpret_cast<void *>(jsCb);
381     // async callback, jsWork and jsWork->data should be heap object.
382     int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
383         // Js Thread
384         CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
385         if (work->data == nullptr) {
386             delete work;
387             MEDIA_LOGE("workdata is nullptr");
388             return;
389         }
390         AVRecordJsCallback *event = reinterpret_cast<AVRecordJsCallback *>(work->data);
391         std::string request = event->callbackName;
392         MEDIA_LOGI("uv_queue_work_with_qos start, errorcode:%{public}d , errormessage:%{public}s:",
393             event->errorCode, event->errorMsg.c_str());
394         do {
395             CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
396             std::shared_ptr<AutoRef> ref = event->autoRef.lock();
397             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
398 
399             napi_handle_scope scope = nullptr;
400             napi_open_handle_scope(ref->env_, &scope);
401             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
402             ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
403 
404             napi_value jsCallback = nullptr;
405             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
406             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
407                 request.c_str());
408 
409             napi_value msgValStr = nullptr;
410             nstatus = napi_create_string_utf8(ref->env_, event->errorMsg.c_str(), NAPI_AUTO_LENGTH, &msgValStr);
411             CHECK_AND_BREAK_LOG(nstatus == napi_ok && msgValStr != nullptr, "create error message str fail");
412 
413             napi_value args[1] = { nullptr };
414             nstatus = napi_create_error(ref->env_, nullptr, msgValStr, &args[0]);
415             CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr, "create error callback fail");
416 
417             nstatus = CommonNapi::FillErrorArgs(ref->env_, event->errorCode, args[0]);
418             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "create error callback fail");
419 
420             // Call back function
421             napi_value result = nullptr;
422             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
423             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
424         } while (0);
425         delete event;
426         delete work;
427     }, uv_qos_user_initiated);
428     CHECK_AND_RETURN_LOG(ret == 0, "fail to uv_queue_work_with_qos task");
429 
430     CANCEL_SCOPE_EXIT_GUARD(0);
431     CANCEL_SCOPE_EXIT_GUARD(1);
432 }
433 
GetJsResult(napi_env env,napi_value & result)434 napi_status AudioCaptureChangeInfoJsCallback::GetJsResult(napi_env env, napi_value &result)
435 {
436     napi_status ret = napi_ok;
437     bool setRet = true;
438     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &result)) == napi_ok, ret);
439 
440     setRet = CommonNapi::SetPropertyInt32(env, result, "streamId", value_.sessionId);
441     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
442     setRet = CommonNapi::SetPropertyInt32(env, result, "clientUid", value_.clientUID);
443     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
444     setRet = CommonNapi::SetPropertyInt32(env, result, "capturerState", value_.capturerState);
445     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
446     setRet = CommonNapi::SetPropertyBool(env, result, "muted", value_.muted);
447     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
448 
449     napi_value captureInfo;
450     napi_value deviceDescriptors;
451     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &captureInfo)) == napi_ok, ret);
452     CHECK_AND_RETURN_RET((ret = napi_create_array_with_length(env, 1, &deviceDescriptors)) == napi_ok, ret);
453     CHECK_AND_RETURN_RET((ret = SetAudioCapturerInfo(env, captureInfo, result)) == napi_ok, ret);
454     CHECK_AND_RETURN_RET((ret = SetDeviceInfo(env, deviceDescriptors, result)) == napi_ok, ret);
455     return ret;
456 }
457 
SetAudioCapturerInfo(napi_env env,napi_value & captureInfo,napi_value & result)458 napi_status AudioCaptureChangeInfoJsCallback::SetAudioCapturerInfo(napi_env env,
459     napi_value &captureInfo, napi_value &result)
460 {
461     bool setRet = true;
462     setRet = CommonNapi::SetPropertyInt32(env, captureInfo, "source",
463         static_cast<int32_t>(value_.capturerInfo.sourceType));
464     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
465     setRet = CommonNapi::SetPropertyInt32(env, captureInfo, "capturerFlags", value_.capturerInfo.capturerFlags);
466     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
467     napi_set_named_property(env, result, "capturerInfo", captureInfo);
468     return napi_ok;
469 }
470 
SetDeviceProperty(napi_env env,napi_value & element)471 napi_status AudioCaptureChangeInfoJsCallback::SetDeviceProperty(napi_env env, napi_value &element)
472 {
473     bool setRet = true;
474     setRet = CommonNapi::SetPropertyInt32(env, element, "deviceRole",
475         static_cast<int32_t>(value_.inputDeviceInfo.deviceRole));
476     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
477     setRet = CommonNapi::SetPropertyInt32(env, element, "deviceType",
478         static_cast<int32_t>(value_.inputDeviceInfo.deviceType));
479     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
480     setRet = CommonNapi::SetPropertyInt32(env, element, "id", value_.inputDeviceInfo.deviceId);
481     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
482     setRet = CommonNapi::SetPropertyString(env, element, "name", value_.inputDeviceInfo.deviceName);
483     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
484     setRet = CommonNapi::SetPropertyString(env, element, "address", value_.inputDeviceInfo.macAddress);
485     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
486     setRet = CommonNapi::SetPropertyString(env, element, "networkId", value_.inputDeviceInfo.networkId);
487     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
488     setRet = CommonNapi::SetPropertyString(env, element, "displayName", value_.inputDeviceInfo.displayName);
489     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
490     setRet = CommonNapi::SetPropertyInt32(env, element, "interruptGroupId",
491         value_.inputDeviceInfo.interruptGroupId);
492     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
493     setRet = CommonNapi::SetPropertyInt32(env, element, "volumeGroupId",
494         value_.inputDeviceInfo.volumeGroupId);
495     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
496     return napi_ok;
497 }
498 
SetDeviceInfo(napi_env env,napi_value & deviceDescriptors,napi_value & result)499 napi_status AudioCaptureChangeInfoJsCallback::SetDeviceInfo(napi_env env,
500     napi_value &deviceDescriptors, napi_value &result)
501 {
502     napi_value element;
503     napi_create_object(env, &element);
504     CHECK_AND_RETURN_RET(SetDeviceProperty(env, element) == napi_ok, napi_generic_failure);
505 
506     bool setRet = true;
507     napi_value sampleRates;
508     setRet = CommonNapi::AddArrayInt(env, sampleRates,
509         std::vector<int32_t>(value_.inputDeviceInfo.audioStreamInfo.samplingRate.begin(),
510         value_.inputDeviceInfo.audioStreamInfo.samplingRate.end()));
511     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
512     napi_set_named_property(env, element, "sampleRates", sampleRates);
513 
514     napi_value channelCounts;
515     setRet = CommonNapi::AddArrayInt(env, channelCounts,
516         std::vector<int32_t>(value_.inputDeviceInfo.audioStreamInfo.channels.begin(),
517         value_.inputDeviceInfo.audioStreamInfo.channels.end()));
518     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
519     napi_set_named_property(env, element, "channelCounts", channelCounts);
520 
521     napi_value channelMasks;
522     setRet = CommonNapi::AddArrayInt(env, channelMasks, std::vector<int32_t>({value_.inputDeviceInfo.channelMasks}));
523     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
524     napi_set_named_property(env, element, "channelMasks", channelMasks);
525 
526     napi_value channelIndexMasks;
527     setRet = CommonNapi::AddArrayInt(env, channelIndexMasks,
528         std::vector<int32_t>({value_.inputDeviceInfo.channelIndexMasks}));
529     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
530     napi_set_named_property(env, element, "channelIndexMasks", channelIndexMasks);
531 
532     napi_value encodingTypes;
533     setRet = CommonNapi::AddArrayInt(env, encodingTypes,
534         std::vector<int32_t>({value_.inputDeviceInfo.audioStreamInfo.encoding}));
535     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
536     napi_set_named_property(env, element, "encodingTypes", encodingTypes);
537 
538     napi_set_element(env, deviceDescriptors, 0, element);
539     napi_set_named_property(env, result, "deviceDescriptors", deviceDescriptors);
540     return napi_ok;
541 }
542 } // namespace Media
543 } // namespace OHOS