• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "NapiCapturerPositionCallback"
17 #endif
18 
19 #include "js_native_api.h"
20 #include "napi_capturer_position_callback.h"
21 #include "napi_audio_capturer_callbacks.h"
22 #include "napi_param_utils.h"
23 
24 namespace OHOS {
25 namespace AudioStandard {
NapiCapturerPositionCallback(napi_env env)26 NapiCapturerPositionCallback::NapiCapturerPositionCallback(napi_env env)
27     : env_(env)
28 {
29     AUDIO_DEBUG_LOG("NapiCapturerPositionCallback: instance create");
30 }
31 
~NapiCapturerPositionCallback()32 NapiCapturerPositionCallback::~NapiCapturerPositionCallback()
33 {
34     if (regAcPosTsfn_) {
35         napi_release_threadsafe_function(acPosTsfn_, napi_tsfn_abort);
36     }
37     AUDIO_DEBUG_LOG("NapiCapturerPositionCallback: instance destroy");
38 }
39 
SaveCallbackReference(const std::string & callbackName,napi_value args)40 void NapiCapturerPositionCallback::SaveCallbackReference(const std::string &callbackName, napi_value args)
41 {
42     std::lock_guard<std::mutex> lock(mutex_);
43     // create function that will operate while save callback reference success.
44     std::function<void(std::shared_ptr<AutoRef> generatedCallback)> successed =
45         [this](std::shared_ptr<AutoRef> generatedCallback) {
46         capturerPositionCallback_ = generatedCallback;
47     };
48     SaveCallbackReferenceInner(callbackName, args, successed);
49 }
50 
RemoveCallbackReference(const std::string & callbackName,napi_env env,napi_value callback)51 void NapiCapturerPositionCallback::RemoveCallbackReference(const std::string &callbackName, napi_env env,
52     napi_value callback)
53 {
54     std::lock_guard<std::mutex> lock(mutex_);
55     // create function that will operate while remove callback reference success.
56     std::function<void()> successed =
57         [this]() {
58         capturerPositionCallback_ = nullptr;
59         };
60     RemoveCallbackReferenceInner(callbackName, env, callback, successed);
61 }
62 
CreateCapturePositionTsfn(napi_env env)63 void NapiCapturerPositionCallback::CreateCapturePositionTsfn(napi_env env)
64 {
65     regAcPosTsfn_ = true;
66     std::string callbackName = "CapturePosition";
67     napi_value cbName;
68     napi_create_string_utf8(env, callbackName.c_str(), callbackName.length(), &cbName);
69     napi_create_threadsafe_function(env, nullptr, nullptr, cbName, 0, 1, nullptr,
70         CapturePostionTsfnFinalize, nullptr, SafeJsCallbackCapturerPositionWork, &acPosTsfn_);
71 }
72 
GetCapturePositionFlag()73 bool NapiCapturerPositionCallback::GetCapturePositionFlag()
74 {
75     return regAcPosTsfn_;
76 }
77 
OnMarkReached(const int64_t & framePosition)78 void NapiCapturerPositionCallback::OnMarkReached(const int64_t &framePosition)
79 {
80     std::lock_guard<std::mutex> lock(mutex_);
81     AUDIO_DEBUG_LOG("NapiCapturerPositionCallback: mark reached");
82     CHECK_AND_RETURN_LOG(capturerPositionCallback_ != nullptr, "Cannot find the reference of position callback");
83 
84     std::unique_ptr<CapturerPositionJsCallback> cb = std::make_unique<CapturerPositionJsCallback>();
85     CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
86     cb->callback = capturerPositionCallback_;
87     cb->callbackName = MARK_REACH_CALLBACK_NAME;
88     cb->position = framePosition;
89     return OnJsCapturerPositionCallback(cb);
90 }
91 
SafeJsCallbackCapturerPositionWork(napi_env env,napi_value js_cb,void * context,void * data)92 void NapiCapturerPositionCallback::SafeJsCallbackCapturerPositionWork(
93     napi_env env, napi_value js_cb, void *context, void *data)
94 {
95     CapturerPositionJsCallback *event = reinterpret_cast<CapturerPositionJsCallback *>(data);
96     CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback != nullptr),
97         "OnJsCapturerPositionCallback: no memory");
98     std::shared_ptr<CapturerPositionJsCallback> safeContext(
99         static_cast<CapturerPositionJsCallback*>(data),
100         [](CapturerPositionJsCallback *ptr) {
101             delete ptr;
102     });
103     std::string request = event->callbackName;
104     napi_ref callback = event->callback->cb_;
105     napi_handle_scope scope = nullptr;
106     napi_open_handle_scope(env, &scope);
107     CHECK_AND_RETURN_LOG(scope != nullptr, "scope is nullptr");
108     AUDIO_INFO_LOG("SafeJsCallbackCapturerPositionWork: safe js callback working.");
109 
110     do {
111         napi_value jsCallback = nullptr;
112         napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
113         CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
114             request.c_str());
115 
116         napi_value args[ARGS_ONE] = { nullptr };
117         napi_create_int64(env, event->position, &args[PARAM0]);
118         CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[PARAM0] != nullptr,
119             "%{public}s fail to create position callback", request.c_str());
120 
121         const size_t argCount = ARGS_ONE;
122         napi_value result = nullptr;
123         nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
124         CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call position callback", request.c_str());
125     } while (0);
126     napi_close_handle_scope(env, scope);
127 }
128 
CapturePostionTsfnFinalize(napi_env env,void * data,void * hint)129 void NapiCapturerPositionCallback::CapturePostionTsfnFinalize(napi_env env, void *data, void *hint)
130 {
131     AUDIO_INFO_LOG("CapturePostionTsfnFinalize: safe thread resource release.");
132 }
133 
OnJsCapturerPositionCallback(std::unique_ptr<CapturerPositionJsCallback> & jsCb)134 void NapiCapturerPositionCallback::OnJsCapturerPositionCallback(std::unique_ptr<CapturerPositionJsCallback> &jsCb)
135 {
136     if (jsCb.get() == nullptr) {
137         AUDIO_ERR_LOG("OnJsCapturerPositionCallback: jsCb.get() is null");
138         return;
139     }
140 
141     CapturerPositionJsCallback *event = jsCb.release();
142     CHECK_AND_RETURN_LOG((event != nullptr) && (event->callback != nullptr), "event is nullptr.");
143 
144     napi_acquire_threadsafe_function(acPosTsfn_);
145     napi_call_threadsafe_function(acPosTsfn_, event, napi_tsfn_blocking);
146 }
147 
GetEnv()148 napi_env &NapiCapturerPositionCallback::GetEnv()
149 {
150     return env_;
151 }
152 
GetCallback(const std::string & callbackName)153 std::shared_ptr<AutoRef> NapiCapturerPositionCallback::GetCallback(const std::string &callbackName)
154 {
155     std::shared_ptr<AutoRef> cb = nullptr;
156     if (callbackName == MARK_REACH_CALLBACK_NAME) {
157         return capturerPositionCallback_;
158     }
159     return cb;
160 }
161 
CheckIfTargetCallbackName(const std::string & callbackName)162 bool NapiCapturerPositionCallback::CheckIfTargetCallbackName(const std::string &callbackName)
163 {
164     if (callbackName == MARK_REACH_CALLBACK_NAME) {
165         return true;
166     }
167     return false;
168 }
169 }  // namespace AudioStandard
170 }  // namespace OHOS