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 "NapiAudioSpatializationMgrCallback"
17 #endif
18
19 #include "js_native_api.h"
20 #include "napi_audio_spatialization_manager_callback.h"
21 #include "audio_errors.h"
22 #include "audio_manager_log.h"
23 #include "napi_param_utils.h"
24 #include "napi_audio_error.h"
25 #include "napi_audio_manager_callbacks.h"
26
27 namespace OHOS {
28 namespace AudioStandard {
29 bool NapiAudioSpatializationEnabledChangeCallback::onSpatializationEnabledChangeFlag_;
30 bool NapiAudioHeadTrackingEnabledChangeCallback::onHeadTrackingEnabledChangeFlag_;
31 using namespace std;
NapiAudioSpatializationEnabledChangeCallback(napi_env env)32 NapiAudioSpatializationEnabledChangeCallback::NapiAudioSpatializationEnabledChangeCallback(napi_env env)
33 : env_(env)
34 {
35 AUDIO_DEBUG_LOG("NapiAudioSpatializationEnabledChangeCallback: instance create");
36 }
37
~NapiAudioSpatializationEnabledChangeCallback()38 NapiAudioSpatializationEnabledChangeCallback::~NapiAudioSpatializationEnabledChangeCallback()
39 {
40 if (regAmSpatEnable_) {
41 napi_release_threadsafe_function(amSpatEnableTsfn_, napi_tsfn_abort);
42 }
43 AUDIO_DEBUG_LOG("NapiAudioSpatializationEnabledChangeCallback: instance destroy");
44 }
45
CreateSpatEnableTsfn(napi_env env)46 void NapiAudioSpatializationEnabledChangeCallback::CreateSpatEnableTsfn(napi_env env)
47 {
48 napi_value cbName;
49 regAmSpatEnable_ = true;
50 std::string callbackName = "volumeChange";
51 napi_create_string_utf8(env, callbackName.c_str(), callbackName.length(), &cbName);
52 napi_create_threadsafe_function(env_, nullptr, nullptr, cbName, 0, 1, nullptr,
53 SpatializationEnabledTsfnFinalize, nullptr, SafeJsCallbackSpatializationEnabledWork,
54 &amSpatEnableTsfn_);
55 }
56
GetSpatEnableTsfnFlag()57 bool NapiAudioSpatializationEnabledChangeCallback::GetSpatEnableTsfnFlag()
58 {
59 return regAmSpatEnable_;
60 }
61
SaveSpatializationEnabledChangeCallbackReference(napi_value args,const std::string & cbName)62 void NapiAudioSpatializationEnabledChangeCallback::SaveSpatializationEnabledChangeCallbackReference(napi_value args,
63 const std::string &cbName)
64 {
65 std::lock_guard<std::mutex> lock(mutex_);
66 napi_ref callback = nullptr;
67 const int32_t refCount = ARGS_ONE;
68
69 if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_CALLBACK_NAME)) {
70 for (auto it = spatializationEnabledChangeCbList_.begin();
71 it != spatializationEnabledChangeCbList_.end(); ++it) {
72 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
73 CHECK_AND_RETURN_LOG(!isSameCallback, "SaveCallbackReference: spatialization manager has same callback");
74 }
75
76 napi_status status = napi_create_reference(env_, args, refCount, &callback);
77 CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
78 "NapiAudioSpatializationEnabledChangeCallback: creating reference for callback fail");
79
80 std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
81 CHECK_AND_RETURN_LOG(cb != nullptr, "NapiAudioSpatializationEnabledChangeCallback: creating callback failed");
82 spatializationEnabledChangeCbList_.push_back(cb);
83 } else if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
84 for (auto it = spatializationEnabledChangeCbForAnyDeviceList_.begin();
85 it != spatializationEnabledChangeCbForAnyDeviceList_.end(); ++it) {
86 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
87 CHECK_AND_RETURN_LOG(!isSameCallback, "SaveCallbackReference: spatialization manager has same callback");
88 }
89
90 napi_status status = napi_create_reference(env_, args, refCount, &callback);
91 CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
92 "NapiAudioSpatializationEnabledChangeCallback: creating reference for callback fail");
93
94 std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
95 CHECK_AND_RETURN_LOG(cb != nullptr, "NapiAudioSpatializationEnabledChangeCallback: creating callback failed");
96 spatializationEnabledChangeCbForAnyDeviceList_.push_back(cb);
97 }
98 }
99
RemoveSpatializationEnabledChangeCallbackReference(napi_env env,napi_value args,const std::string & cbName)100 void NapiAudioSpatializationEnabledChangeCallback::RemoveSpatializationEnabledChangeCallbackReference(napi_env env,
101 napi_value args, const std::string &cbName)
102 {
103 std::lock_guard<std::mutex> lock(mutex_);
104 if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_CALLBACK_NAME)) {
105 for (auto it = spatializationEnabledChangeCbList_.begin();
106 it != spatializationEnabledChangeCbList_.end(); ++it) {
107 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
108 if (isSameCallback) {
109 AUDIO_INFO_LOG("RemoveSpatializationEnabledChangeCallbackReference: find js callback, erase it");
110 spatializationEnabledChangeCbList_.erase(it);
111 return;
112 }
113 }
114 } else if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
115 for (auto it = spatializationEnabledChangeCbForAnyDeviceList_.begin();
116 it != spatializationEnabledChangeCbForAnyDeviceList_.end(); ++it) {
117 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
118 if (isSameCallback) {
119 AUDIO_INFO_LOG("RemoveSpatializationEnabledChangeCallbackReference: find js callback, erase it");
120 spatializationEnabledChangeCbForAnyDeviceList_.erase(it);
121 return;
122 }
123 }
124 }
125 AUDIO_INFO_LOG("RemoveSpatializationEnabledChangeCallbackReference: js callback no find");
126 }
127
RemoveAllSpatializationEnabledChangeCallbackReference(const std::string & cbName)128 void NapiAudioSpatializationEnabledChangeCallback::RemoveAllSpatializationEnabledChangeCallbackReference(
129 const std::string &cbName)
130 {
131 std::lock_guard<std::mutex> lock(mutex_);
132 if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_CALLBACK_NAME)) {
133 spatializationEnabledChangeCbList_.clear();
134 } else if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
135 spatializationEnabledChangeCbForAnyDeviceList_.clear();
136 }
137 AUDIO_INFO_LOG("RemoveAllSpatializationEnabledChangeCallbackReference: remove all js callbacks success");
138 }
139
GetSpatializationEnabledChangeCbListSize(const std::string & cbName)140 int32_t NapiAudioSpatializationEnabledChangeCallback::GetSpatializationEnabledChangeCbListSize(
141 const std::string &cbName)
142 {
143 std::lock_guard<std::mutex> lock(mutex_);
144 return ((!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_CALLBACK_NAME)) ? spatializationEnabledChangeCbList_.size():
145 spatializationEnabledChangeCbForAnyDeviceList_.size());
146 }
147
OnSpatializationEnabledChange(const bool & enabled)148 void NapiAudioSpatializationEnabledChangeCallback::OnSpatializationEnabledChange(const bool &enabled)
149 {
150 AUDIO_INFO_LOG("OnSpatializationEnabledChange entered");
151 std::lock_guard<std::mutex> lock(mutex_);
152
153 for (auto it = spatializationEnabledChangeCbList_.begin(); it != spatializationEnabledChangeCbList_.end(); it++) {
154 std::unique_ptr<AudioSpatializationEnabledJsCallback> cb =
155 std::make_unique<AudioSpatializationEnabledJsCallback>();
156 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory!!");
157 cb->callback = (*it);
158 cb->enabled = enabled;
159 onSpatializationEnabledChangeFlag_ = true;
160 OnJsCallbackSpatializationEnabled(cb);
161 }
162 return;
163 }
164
OnSpatializationEnabledChangeForAnyDevice(const std::shared_ptr<AudioDeviceDescriptor> & deviceDescriptor,const bool & enabled)165 void NapiAudioSpatializationEnabledChangeCallback::OnSpatializationEnabledChangeForAnyDevice(
166 const std::shared_ptr<AudioDeviceDescriptor> &deviceDescriptor, const bool &enabled)
167 {
168 AUDIO_INFO_LOG("OnSpatializationEnabledChange by the speified device entered");
169 std::lock_guard<std::mutex> lock(mutex_);
170
171 for (auto it = spatializationEnabledChangeCbList_.begin(); it != spatializationEnabledChangeCbList_.end(); it++) {
172 std::unique_ptr<AudioSpatializationEnabledJsCallback> cb =
173 std::make_unique<AudioSpatializationEnabledJsCallback>();
174 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory!!");
175 cb->callback = (*it);
176 cb->enabled = enabled;
177 onSpatializationEnabledChangeFlag_ = true;
178 OnJsCallbackSpatializationEnabled(cb);
179 }
180 for (auto it = spatializationEnabledChangeCbForAnyDeviceList_.begin();
181 it != spatializationEnabledChangeCbForAnyDeviceList_.end(); it++) {
182 std::unique_ptr<AudioSpatializationEnabledJsCallback> cb =
183 std::make_unique<AudioSpatializationEnabledJsCallback>();
184 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory!!");
185 cb->callback = (*it);
186 cb->deviceDescriptor = deviceDescriptor;
187 cb->enabled = enabled;
188 onSpatializationEnabledChangeFlag_ = false;
189 OnJsCallbackSpatializationEnabled(cb);
190 }
191
192 return;
193 }
194
SafeJsCallbackSpatializationEnabledWork(napi_env env,napi_value js_cb,void * context,void * data)195 void NapiAudioSpatializationEnabledChangeCallback::SafeJsCallbackSpatializationEnabledWork(
196 napi_env env, napi_value js_cb, void *context, void *data)
197 {
198 AudioSpatializationEnabledJsCallback *event = reinterpret_cast<AudioSpatializationEnabledJsCallback *>(data);
199 CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback != nullptr),
200 "OnJsCallbackSpatializationEnabled: no memory");
201 std::shared_ptr<AudioSpatializationEnabledJsCallback> safeContext(
202 static_cast<AudioSpatializationEnabledJsCallback*>(data),
203 [](AudioSpatializationEnabledJsCallback *ptr) {
204 delete ptr;
205 });
206 napi_ref callback = event->callback->cb_;
207 napi_handle_scope scope = nullptr;
208 napi_open_handle_scope(env, &scope);
209 CHECK_AND_RETURN_LOG(scope != nullptr, "scope is nullptr");
210 AUDIO_INFO_LOG("SafeJsCallbackSpatializationEnabledWork: safe js callback working.");
211
212 do {
213 napi_value jsCallback = nullptr;
214 napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
215 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "callback get reference value fail");
216 napi_value args[ARGS_ONE] = { nullptr };
217 const size_t argCount = ARGS_ONE;
218 napi_value result = nullptr;
219
220 if (onSpatializationEnabledChangeFlag_) {
221 NapiParamUtils::SetValueBoolean(env, event->enabled, args[PARAM0]);
222 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[PARAM0] != nullptr, "fail to convert to jsobj");
223 } else {
224 AudioSpatialEnabledStateForDevice audioSpatialEnabledStateForDevice;
225 audioSpatialEnabledStateForDevice.deviceDescriptor = event->deviceDescriptor;
226 audioSpatialEnabledStateForDevice.enabled = event->enabled;
227 NapiParamUtils::SetAudioSpatialEnabledStateForDevice(env,
228 audioSpatialEnabledStateForDevice, args[PARAM0]);
229 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[PARAM0] != nullptr, "fail to convert to jsobj");
230 }
231
232 nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
233 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "Fail to call spatialization enabled callback");
234 } while (0);
235 napi_close_handle_scope(env, scope);
236 }
237
SpatializationEnabledTsfnFinalize(napi_env env,void * data,void * hint)238 void NapiAudioSpatializationEnabledChangeCallback::SpatializationEnabledTsfnFinalize(
239 napi_env env, void *data, void *hint)
240 {
241 AUDIO_INFO_LOG("SpatializationEnabledTsfnFinalize: safe thread resource release.");
242 }
243
OnJsCallbackSpatializationEnabled(std::unique_ptr<AudioSpatializationEnabledJsCallback> & jsCb)244 void NapiAudioSpatializationEnabledChangeCallback::OnJsCallbackSpatializationEnabled(
245 std::unique_ptr<AudioSpatializationEnabledJsCallback> &jsCb)
246 {
247 if (jsCb.get() == nullptr) {
248 AUDIO_ERR_LOG("OnJsCallbackSpatializationEnabled: jsCb.get() is null");
249 return;
250 }
251
252 AudioSpatializationEnabledJsCallback *event = jsCb.release();
253 CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback != nullptr), "event is nullptr.");
254 event->callbackName = "AudioSpatializationEnabled";
255
256 napi_acquire_threadsafe_function(amSpatEnableTsfn_);
257 napi_call_threadsafe_function(amSpatEnableTsfn_, event, napi_tsfn_blocking);
258 }
259
NapiAudioCurrentSpatializationEnabledChangeCallback(napi_env env)260 NapiAudioCurrentSpatializationEnabledChangeCallback::NapiAudioCurrentSpatializationEnabledChangeCallback(
261 napi_env env) : env_(env)
262 {
263 AUDIO_DEBUG_LOG("NapiAudioCurrentSpatializationEnabledChangeCallback: instance create");
264 }
265
~NapiAudioCurrentSpatializationEnabledChangeCallback()266 NapiAudioCurrentSpatializationEnabledChangeCallback::~NapiAudioCurrentSpatializationEnabledChangeCallback()
267 {
268 if (regAmSpatEnableForCurrentDevice_) {
269 napi_release_threadsafe_function(amSpatEnableForCurrentDeviceTsfn_, napi_tsfn_abort);
270 }
271 AUDIO_DEBUG_LOG("NapiAudioCurrentSpatializationEnabledChangeCallback: instance destroy");
272 }
273
SaveCurrentSpatializationEnabledChangeCallbackReference(napi_value args,const std::string & cbName)274 void NapiAudioCurrentSpatializationEnabledChangeCallback::SaveCurrentSpatializationEnabledChangeCallbackReference(
275 napi_value args, const std::string &cbName)
276 {
277 std::lock_guard<std::mutex> lock(mutex_);
278 napi_ref callback = nullptr;
279 const int32_t refCount = ARGS_ONE;
280 for (auto it = spatializationEnabledChangeCbForCurrentDeviceList_.begin();
281 it != spatializationEnabledChangeCbForCurrentDeviceList_.end(); ++it) {
282 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
283 CHECK_AND_RETURN_LOG(!isSameCallback, "SaveCallbackReference: spatialization manager has same callback");
284 }
285
286 napi_status status = napi_create_reference(env_, args, refCount, &callback);
287 CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
288 "NapiAudioCurrentSpatializationEnabledChangeCallback: creating reference for callback fail");
289
290 std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
291 CHECK_AND_RETURN_LOG(cb != nullptr, "NapiAudioCurrentSpatializationEnabledChangeCallback:creating callback failed");
292
293 spatializationEnabledChangeCbForCurrentDeviceList_.push_back(cb);
294 }
295
CreateCurrentSpatEnableForCurrentDeviceTsfn(napi_env env)296 void NapiAudioCurrentSpatializationEnabledChangeCallback::CreateCurrentSpatEnableForCurrentDeviceTsfn(napi_env env)
297 {
298 regAmSpatEnableForCurrentDevice_ = true;
299 napi_value cbName;
300 std::string callbackName = "AudioSpatializationEnabledForCurrentDevice";
301 napi_create_string_utf8(env, callbackName.c_str(), callbackName.length(), &cbName);
302 napi_create_threadsafe_function(env, nullptr, nullptr, cbName, 0, 1, nullptr,
303 SpatializationEnabledForCurrentDeviceTsfnFinalize, nullptr,
304 SafeJsCallbackSpatializationEnabledForCurrentDeviceWork, &amSpatEnableForCurrentDeviceTsfn_);
305 }
306
GetCurrentSpatEnableForCurrentDeviceTsfnFlag()307 bool NapiAudioCurrentSpatializationEnabledChangeCallback::GetCurrentSpatEnableForCurrentDeviceTsfnFlag()
308 {
309 return regAmSpatEnableForCurrentDevice_;
310 }
311
RemoveCurrentSpatializationEnabledChangeCallbackReference(napi_env env,napi_value args,const std::string & cbName)312 void NapiAudioCurrentSpatializationEnabledChangeCallback::RemoveCurrentSpatializationEnabledChangeCallbackReference(
313 napi_env env, napi_value args, const std::string &cbName)
314 {
315 std::lock_guard<std::mutex> lock(mutex_);
316 for (auto it = spatializationEnabledChangeCbForCurrentDeviceList_.begin();
317 it != spatializationEnabledChangeCbForCurrentDeviceList_.end(); ++it) {
318 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
319 if (isSameCallback) {
320 AUDIO_INFO_LOG("RemoveCurrentSpatializationEnabledChangeCallbackReference: find js callback,"
321 "erase it");
322 spatializationEnabledChangeCbForCurrentDeviceList_.erase(it);
323 return;
324 }
325 }
326 AUDIO_INFO_LOG("RemoveCurrentSpatializationEnabledChangeCallbackReference: js callback no find");
327 }
328
RemoveAllCurrentSpatializationEnabledChangeCallbackReference(const std::string & cbName)329 void NapiAudioCurrentSpatializationEnabledChangeCallback::RemoveAllCurrentSpatializationEnabledChangeCallbackReference(
330 const std::string &cbName)
331 {
332 std::lock_guard<std::mutex> lock(mutex_);
333 spatializationEnabledChangeCbForCurrentDeviceList_.clear();
334
335 AUDIO_INFO_LOG("RemoveAllCurrentSpatializationEnabledChangeCallbackReference: remove all js callbacks"
336 "success");
337 }
338
GetCurrentSpatializationEnabledChangeCbListSize(const std::string & cbName)339 int32_t NapiAudioCurrentSpatializationEnabledChangeCallback::GetCurrentSpatializationEnabledChangeCbListSize(
340 const std::string &cbName)
341 {
342 std::lock_guard<std::mutex> lock(mutex_);
343 return spatializationEnabledChangeCbForCurrentDeviceList_.size();
344 }
345
OnSpatializationEnabledChangeForCurrentDevice(const bool & enabled)346 void NapiAudioCurrentSpatializationEnabledChangeCallback::OnSpatializationEnabledChangeForCurrentDevice(
347 const bool &enabled)
348 {
349 AUDIO_INFO_LOG("OnSpatializationEnabledChangeForCurrentDevice entered");
350 std::lock_guard<std::mutex> lock(mutex_);
351
352 for (auto it = spatializationEnabledChangeCbForCurrentDeviceList_.begin();
353 it != spatializationEnabledChangeCbForCurrentDeviceList_.end(); it++) {
354 std::unique_ptr<AudioSpatializationEnabledForCurrentDeviceJsCallback> cb =
355 std::make_unique<AudioSpatializationEnabledForCurrentDeviceJsCallback>();
356 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory!!");
357 cb->callback = (*it);
358 cb->enabled = enabled;
359 OnJsCallbackSpatializationEnabledForCurrentDevice(cb);
360 }
361
362 return;
363 }
364
SafeJsCallbackSpatializationEnabledForCurrentDeviceWork(napi_env env,napi_value js_cb,void * context,void * data)365 void NapiAudioCurrentSpatializationEnabledChangeCallback::SafeJsCallbackSpatializationEnabledForCurrentDeviceWork(
366 napi_env env, napi_value js_cb, void *context, void *data)
367 {
368 AudioSpatializationEnabledForCurrentDeviceJsCallback *event =
369 reinterpret_cast<AudioSpatializationEnabledForCurrentDeviceJsCallback *>(data);
370 CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback != nullptr),
371 "OnJsCallbackSpatializationEnabledForCurrentDevice: no memory");
372 std::shared_ptr<AudioSpatializationEnabledForCurrentDeviceJsCallback> safeContext(
373 static_cast<AudioSpatializationEnabledForCurrentDeviceJsCallback*>(data),
374 [](AudioSpatializationEnabledForCurrentDeviceJsCallback *ptr) {
375 delete ptr;
376 });
377 napi_ref callback = event->callback->cb_;
378 napi_handle_scope scope = nullptr;
379 napi_open_handle_scope(env, &scope);
380 CHECK_AND_RETURN_LOG(scope != nullptr, "scope is nullptr");
381 AUDIO_INFO_LOG("SafeJsCallbackSpatializationEnabledForCurrentDeviceWork: safe js callback working.");
382
383 do {
384 napi_value jsCallback = nullptr;
385 napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
386 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "callback get reference value fail");
387 napi_value args[ARGS_ONE] = { nullptr };
388 NapiParamUtils::SetValueBoolean(env, event->enabled, args[PARAM0]);
389 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[PARAM0] != nullptr, "fail to convert to jsobj");
390
391 const size_t argCount = ARGS_ONE;
392 napi_value result = nullptr;
393
394 nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
395 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "Fail to call head tracking enabled callback");
396 } while (0);
397 napi_close_handle_scope(env, scope);
398 }
399
SpatializationEnabledForCurrentDeviceTsfnFinalize(napi_env env,void * data,void * hint)400 void NapiAudioCurrentSpatializationEnabledChangeCallback::SpatializationEnabledForCurrentDeviceTsfnFinalize(
401 napi_env env, void *data, void *hint)
402 {
403 AUDIO_INFO_LOG("SpatializationEnabledForCurrentDeviceTsfnFinalize: safe thread resource release.");
404 }
405
OnJsCallbackSpatializationEnabledForCurrentDevice(std::unique_ptr<AudioSpatializationEnabledForCurrentDeviceJsCallback> & jsCb)406 void NapiAudioCurrentSpatializationEnabledChangeCallback::OnJsCallbackSpatializationEnabledForCurrentDevice(
407 std::unique_ptr<AudioSpatializationEnabledForCurrentDeviceJsCallback> &jsCb)
408 {
409 if (jsCb.get() == nullptr) {
410 AUDIO_ERR_LOG("OnJsCallbackSpatializationEnabledForCurrentDevice: jsCb.get() is null");
411 return;
412 }
413
414 AudioSpatializationEnabledForCurrentDeviceJsCallback *event = jsCb.release();
415 CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback != nullptr), "event is nullptr.");
416
417 napi_acquire_threadsafe_function(amSpatEnableForCurrentDeviceTsfn_);
418 napi_call_threadsafe_function(amSpatEnableForCurrentDeviceTsfn_, event, napi_tsfn_blocking);
419 }
420
NapiAudioHeadTrackingEnabledChangeCallback(napi_env env)421 NapiAudioHeadTrackingEnabledChangeCallback::NapiAudioHeadTrackingEnabledChangeCallback(napi_env env)
422 : env_(env)
423 {
424 AUDIO_DEBUG_LOG("NapiAudioHeadTrackingEnabledChangeCallback: instance create");
425 }
426
~NapiAudioHeadTrackingEnabledChangeCallback()427 NapiAudioHeadTrackingEnabledChangeCallback::~NapiAudioHeadTrackingEnabledChangeCallback()
428 {
429 if (regAmHeadTrkTsfn_) {
430 napi_release_threadsafe_function(amHeadTrkTsfn_, napi_tsfn_abort);
431 }
432 AUDIO_DEBUG_LOG("NapiAudioHeadTrackingEnabledChangeCallback: instance destroy");
433 }
434
SaveHeadTrackingEnabledChangeCallbackReference(napi_value args,const std::string & cbName)435 void NapiAudioHeadTrackingEnabledChangeCallback::SaveHeadTrackingEnabledChangeCallbackReference(napi_value args,
436 const std::string &cbName)
437 {
438 std::lock_guard<std::mutex> lock(mutex_);
439 napi_ref callback = nullptr;
440 const int32_t refCount = ARGS_ONE;
441 if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_CALLBACK_NAME)) {
442 for (auto it = headTrackingEnabledChangeCbList_.begin(); it != headTrackingEnabledChangeCbList_.end(); ++it) {
443 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
444 CHECK_AND_RETURN_LOG(!isSameCallback, "SaveCallbackReference: spatialization manager has same callback");
445 }
446
447 napi_status status = napi_create_reference(env_, args, refCount, &callback);
448 CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
449 "NapiAudioHeadTrackingEnabledChangeCallback: creating reference for callback fail");
450
451 std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
452 CHECK_AND_RETURN_LOG(cb != nullptr, "NapiAudioHeadTrackingEnabledChangeCallback: creating callback failed");
453
454 headTrackingEnabledChangeCbList_.push_back(cb);
455 } else if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
456 for (auto it = headTrackingEnabledChangeCbForAnyDeviceList_.begin();
457 it != headTrackingEnabledChangeCbForAnyDeviceList_.end(); ++it) {
458 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
459 CHECK_AND_RETURN_LOG(!isSameCallback, "SaveCallbackReference: spatialization manager has same callback");
460 }
461
462 napi_status status = napi_create_reference(env_, args, refCount, &callback);
463 CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
464 "NapiAudioHeadTrackingEnabledChangeCallback: creating reference for callback fail");
465
466 std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
467 CHECK_AND_RETURN_LOG(cb != nullptr, "NapiAudioHeadTrackingEnabledChangeCallback: creating callback failed");
468
469 headTrackingEnabledChangeCbForAnyDeviceList_.push_back(cb);
470 }
471 }
472
CreateHeadTrackingTsfn(napi_env env)473 void NapiAudioHeadTrackingEnabledChangeCallback::CreateHeadTrackingTsfn(napi_env env)
474 {
475 regAmHeadTrkTsfn_ = true;
476 napi_value cbName;
477 std::string callbackName = "AudioHeadTrackingEnabled";
478 napi_create_string_utf8(env, callbackName.c_str(), callbackName.length(), &cbName);
479 napi_create_threadsafe_function(env, nullptr, nullptr, cbName, 0, 1, nullptr,
480 HeadTrackingEnabledTsfnFinalize, nullptr, SafeJsCallbackHeadTrackingEnabledWork,
481 &amHeadTrkTsfn_);
482 }
483
GetHeadTrackingTsfnFlag()484 bool NapiAudioHeadTrackingEnabledChangeCallback::GetHeadTrackingTsfnFlag()
485 {
486 return regAmHeadTrkTsfn_;
487 }
488
RemoveHeadTrackingEnabledChangeCallbackReference(napi_env env,napi_value args,const std::string & cbName)489 void NapiAudioHeadTrackingEnabledChangeCallback::RemoveHeadTrackingEnabledChangeCallbackReference(napi_env env,
490 napi_value args, const std::string &cbName)
491 {
492 std::lock_guard<std::mutex> lock(mutex_);
493 if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_CALLBACK_NAME)) {
494 for (auto it = headTrackingEnabledChangeCbList_.begin(); it != headTrackingEnabledChangeCbList_.end(); ++it) {
495 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
496 if (isSameCallback) {
497 AUDIO_INFO_LOG("RemoveHeadTrackingEnabledChangeCallbackReference: find js callback, erase it");
498 headTrackingEnabledChangeCbList_.erase(it);
499 return;
500 }
501 }
502 } else if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
503 for (auto it = headTrackingEnabledChangeCbForAnyDeviceList_.begin();
504 it != headTrackingEnabledChangeCbForAnyDeviceList_.end(); ++it) {
505 bool isSameCallback = NapiAudioManagerCallback::IsSameCallback(env_, args, (*it)->cb_);
506 if (isSameCallback) {
507 AUDIO_INFO_LOG("RemoveHeadTrackingEnabledChangeCallbackReference: find js callback, erase it");
508 headTrackingEnabledChangeCbForAnyDeviceList_.erase(it);
509 return;
510 }
511 }
512 }
513 AUDIO_INFO_LOG("RemoveHeadTrackingEnabledChangeCallbackReference: js callback no find");
514 }
515
RemoveAllHeadTrackingEnabledChangeCallbackReference(const std::string & cbName)516 void NapiAudioHeadTrackingEnabledChangeCallback::RemoveAllHeadTrackingEnabledChangeCallbackReference(const std::string
517 &cbName)
518 {
519 std::lock_guard<std::mutex> lock(mutex_);
520 if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_CALLBACK_NAME)) {
521 headTrackingEnabledChangeCbList_.clear();
522 } else if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
523 headTrackingEnabledChangeCbForAnyDeviceList_.clear();
524 }
525 AUDIO_INFO_LOG("RemoveAllHeadTrackingEnabledChangeCallbackReference: remove all js callbacks success");
526 }
527
GetHeadTrackingEnabledChangeCbListSize(const std::string & cbName)528 int32_t NapiAudioHeadTrackingEnabledChangeCallback::GetHeadTrackingEnabledChangeCbListSize(const std::string &cbName)
529 {
530 std::lock_guard<std::mutex> lock(mutex_);
531 return ((!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_CALLBACK_NAME)) ? headTrackingEnabledChangeCbList_.size():
532 headTrackingEnabledChangeCbForAnyDeviceList_.size());
533 }
534
OnHeadTrackingEnabledChange(const bool & enabled)535 void NapiAudioHeadTrackingEnabledChangeCallback::OnHeadTrackingEnabledChange(const bool &enabled)
536 {
537 AUDIO_INFO_LOG("OnHeadTrackingEnabledChange entered");
538 std::lock_guard<std::mutex> lock(mutex_);
539
540 for (auto it = headTrackingEnabledChangeCbList_.begin(); it != headTrackingEnabledChangeCbList_.end(); it++) {
541 std::unique_ptr<AudioHeadTrackingEnabledJsCallback> cb =
542 std::make_unique<AudioHeadTrackingEnabledJsCallback>();
543 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory!!");
544 cb->callback = (*it);
545 cb->enabled = enabled;
546 onHeadTrackingEnabledChangeFlag_ = true;
547 OnJsCallbackHeadTrackingEnabled(cb);
548 }
549
550 return;
551 }
552
OnHeadTrackingEnabledChangeForAnyDevice(const std::shared_ptr<AudioDeviceDescriptor> & deviceDescriptor,const bool & enabled)553 void NapiAudioHeadTrackingEnabledChangeCallback::OnHeadTrackingEnabledChangeForAnyDevice(
554 const std::shared_ptr<AudioDeviceDescriptor> &deviceDescriptor, const bool &enabled)
555 {
556 AUDIO_INFO_LOG("OnHeadTrackingEnabledChange by the specified device entered");
557 std::lock_guard<std::mutex> lock(mutex_);
558
559 for (auto it = headTrackingEnabledChangeCbList_.begin(); it != headTrackingEnabledChangeCbList_.end(); it++) {
560 std::unique_ptr<AudioHeadTrackingEnabledJsCallback> cb =
561 std::make_unique<AudioHeadTrackingEnabledJsCallback>();
562 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory!!");
563 cb->callback = (*it);
564 cb->enabled = enabled;
565 onHeadTrackingEnabledChangeFlag_ = true;
566 OnJsCallbackHeadTrackingEnabled(cb);
567 }
568 for (auto it = headTrackingEnabledChangeCbForAnyDeviceList_.begin();
569 it != headTrackingEnabledChangeCbForAnyDeviceList_.end(); it++) {
570 std::unique_ptr<AudioHeadTrackingEnabledJsCallback> cb =
571 std::make_unique<AudioHeadTrackingEnabledJsCallback>();
572 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory!!");
573 cb->callback = (*it);
574 cb->deviceDescriptor = deviceDescriptor;
575 cb->enabled = enabled;
576 onHeadTrackingEnabledChangeFlag_ = false;
577 OnJsCallbackHeadTrackingEnabled(cb);
578 }
579
580 return;
581 }
582
SafeJsCallbackHeadTrackingEnabledWork(napi_env env,napi_value js_cb,void * context,void * data)583 void NapiAudioHeadTrackingEnabledChangeCallback::SafeJsCallbackHeadTrackingEnabledWork(
584 napi_env env, napi_value js_cb, void *context, void *data)
585 {
586 AudioHeadTrackingEnabledJsCallback *event = reinterpret_cast<AudioHeadTrackingEnabledJsCallback *>(data);
587 CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback != nullptr),
588 "OnJsCallbackHeadTrackingEnabled: no memory");
589 std::shared_ptr<AudioHeadTrackingEnabledJsCallback> safeContext(
590 static_cast<AudioHeadTrackingEnabledJsCallback*>(data),
591 [](AudioHeadTrackingEnabledJsCallback *ptr) {
592 delete ptr;
593 });
594 napi_ref callback = event->callback->cb_;
595 napi_handle_scope scope = nullptr;
596 napi_open_handle_scope(env, &scope);
597 CHECK_AND_RETURN_LOG(scope != nullptr, "scope is nullptr");
598 AUDIO_INFO_LOG("SafeJsCallbackHeadTrackingEnabledWork: safe js callback working.");
599
600 do {
601 napi_value jsCallback = nullptr;
602 napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
603 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "callback get reference value fail");
604 napi_value args[ARGS_ONE] = { nullptr };
605 const size_t argCount = ARGS_ONE;
606 napi_value result = nullptr;
607
608 if (onHeadTrackingEnabledChangeFlag_) {
609 NapiParamUtils::SetValueBoolean(env, event->enabled, args[PARAM0]);
610 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[PARAM0] != nullptr, "fail to convert to jsobj");
611 } else {
612 AudioSpatialEnabledStateForDevice audioSpatialEnabledStateForDevice;
613 audioSpatialEnabledStateForDevice.deviceDescriptor = event->deviceDescriptor;
614 audioSpatialEnabledStateForDevice.enabled = event->enabled;
615 NapiParamUtils::SetAudioSpatialEnabledStateForDevice(env,
616 audioSpatialEnabledStateForDevice, args[PARAM0]);
617 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[PARAM0] != nullptr, "fail to convert to jsobj");
618 }
619 nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
620 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "Fail to call head tracking enabled callback");
621 } while (0);
622 napi_close_handle_scope(env, scope);
623 }
624
HeadTrackingEnabledTsfnFinalize(napi_env env,void * data,void * hint)625 void NapiAudioHeadTrackingEnabledChangeCallback::HeadTrackingEnabledTsfnFinalize(napi_env env, void *data, void *hint)
626 {
627 AUDIO_INFO_LOG("HeadTrackingEnabledTsfnFinalize: safe thread resource release.");
628 }
629
OnJsCallbackHeadTrackingEnabled(std::unique_ptr<AudioHeadTrackingEnabledJsCallback> & jsCb)630 void NapiAudioHeadTrackingEnabledChangeCallback::OnJsCallbackHeadTrackingEnabled(
631 std::unique_ptr<AudioHeadTrackingEnabledJsCallback> &jsCb)
632 {
633 if (jsCb.get() == nullptr) {
634 AUDIO_ERR_LOG("OnJsCallbackHeadTrackingEnabled: jsCb.get() is null");
635 return;
636 }
637
638 AudioHeadTrackingEnabledJsCallback *event = jsCb.release();
639 CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback != nullptr), "event is nullptr.");
640
641 napi_acquire_threadsafe_function(amHeadTrkTsfn_);
642 napi_call_threadsafe_function(amHeadTrkTsfn_, event, napi_tsfn_blocking);
643 }
644 } // namespace AudioStandard
645 } // namespace OHOS