1 /*
2 * Copyright (c) 2023 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 #ifndef LOG_TAG
16 #define LOG_TAG "NapiAudioCapturerDeviceChangeCallback"
17 #endif
18
19 #include "napi_audio_capturer_device_change_callback.h"
20 #include "audio_errors.h"
21 #include "audio_capturer_log.h"
22 #include "napi_param_utils.h"
23
24 using namespace std;
25
26 namespace OHOS {
27 namespace AudioStandard {
NapiAudioCapturerDeviceChangeCallback(napi_env env)28 NapiAudioCapturerDeviceChangeCallback::NapiAudioCapturerDeviceChangeCallback(napi_env env)
29 : env_(env)
30 {
31 AUDIO_DEBUG_LOG("Instance create");
32 }
33
~NapiAudioCapturerDeviceChangeCallback()34 NapiAudioCapturerDeviceChangeCallback::~NapiAudioCapturerDeviceChangeCallback()
35 {
36 AUDIO_DEBUG_LOG("Instance destroy");
37 }
38
SaveCallbackReference(napi_value args)39 void NapiAudioCapturerDeviceChangeCallback::SaveCallbackReference(napi_value args)
40 {
41 std::lock_guard<std::mutex> lock(mutex_);
42 napi_ref callback = nullptr;
43 const int32_t refCount = 1;
44
45 napi_status status = napi_create_reference(env_, args, refCount, &callback);
46 CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
47 "Creating reference for callback fail");
48
49 callback_ = callback;
50 }
51
ContainSameJsCallback(napi_value args)52 bool NapiAudioCapturerDeviceChangeCallback::ContainSameJsCallback(napi_value args)
53 {
54 bool isEquals = false;
55 napi_value copyValue = nullptr;
56
57 napi_get_reference_value(env_, callback_, ©Value);
58 CHECK_AND_RETURN_RET_LOG(args != nullptr, false, "args is nullptr");
59
60 CHECK_AND_RETURN_RET_LOG(napi_strict_equals(env_, copyValue, args, &isEquals) == napi_ok, false,
61 "Get napi_strict_equals failed");
62
63 return isEquals;
64 }
65
OnStateChange(const DeviceInfo & deviceInfo)66 void NapiAudioCapturerDeviceChangeCallback::OnStateChange(const DeviceInfo &deviceInfo)
67 {
68 OnJsCallbackCapturerDeviceInfo(callback_, deviceInfo);
69 }
70
WorkCallbackCompleted(uv_work_t * work,int status)71 void NapiAudioCapturerDeviceChangeCallback::WorkCallbackCompleted(uv_work_t *work, int status)
72 {
73 // Js Thread
74 std::shared_ptr<AudioCapturerDeviceChangeJsCallback> context(
75 static_cast<AudioCapturerDeviceChangeJsCallback*>(work->data),
76 [work](AudioCapturerDeviceChangeJsCallback* ptr) {
77 delete ptr;
78 delete work;
79 });
80
81 AudioCapturerDeviceChangeJsCallback *event = reinterpret_cast<AudioCapturerDeviceChangeJsCallback*>(work->data);
82 CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback_) != nullptr,
83 "OnJsCallbackCapturerDeviceInfo: no memory");
84
85 napi_env env = event->env_;
86 napi_ref callback = event->callback_;
87
88 napi_handle_scope scope = nullptr;
89 napi_open_handle_scope(env, &scope);
90 CHECK_AND_RETURN_LOG(scope != nullptr, "scope is nullptr");
91 do {
92 napi_value jsCallback = nullptr;
93 napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
94 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "Callback get reference value fail");
95 // Call back function
96 napi_value args[ARGS_ONE] = { nullptr };
97 NapiParamUtils::SetValueDeviceInfo(env, event->deviceInfo_, args[0]);
98 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[PARAM0] != nullptr,
99 " Fail to convert to jsobj");
100 const size_t argCount = ARGS_ONE;
101 napi_value result = nullptr;
102 nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
103 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "Fail to call devicechange callback");
104 } while (0);
105 napi_close_handle_scope(env, scope);
106 }
107
OnJsCallbackCapturerDeviceInfo(napi_ref method,const DeviceInfo & deviceInfo)108 void NapiAudioCapturerDeviceChangeCallback::OnJsCallbackCapturerDeviceInfo(napi_ref method,
109 const DeviceInfo &deviceInfo)
110 {
111 uv_loop_s *loop = nullptr;
112 napi_get_uv_event_loop(env_, &loop);
113 CHECK_AND_RETURN_LOG(loop != nullptr, "Loop is nullptr");
114 CHECK_AND_RETURN_LOG(method != nullptr, "method is nullptr");
115
116 uv_work_t *work = new(std::nothrow) uv_work_t;
117 CHECK_AND_RETURN_LOG(work != nullptr, "OnJsCallbackCapturerDeviceInfo: no memory");
118
119 work->data = new AudioCapturerDeviceChangeJsCallback {method, env_, deviceInfo};
120 if (work->data == nullptr) {
121 AUDIO_ERR_LOG("work data malloc failed: No memory");
122 delete work;
123 return;
124 }
125
126 int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, WorkCallbackCompleted);
127 if (ret != 0) {
128 AUDIO_ERR_LOG("Failed to execute libuv work queue");
129 if (work != nullptr) {
130 if (work->data != nullptr) {
131 delete reinterpret_cast<AudioCapturerDeviceChangeJsCallback*>(work->data);
132 }
133 delete work;
134 }
135 }
136 }
137 } // namespace AudioStandard
138 } // namespace OHOS
139