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