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
16 #include "napi_avcast_controller_callback.h"
17 #include "avsession_log.h"
18 #include "avsession_trace.h"
19 #include "napi_control_command.h"
20 #include "napi_meta_data.h"
21 #include "napi_playback_state.h"
22 #include "napi_media_description.h"
23 #include "napi_queue_item.h"
24 #include "napi_utils.h"
25 #include "napi_cast_control_command.h"
26
27 namespace OHOS::AVSession {
NapiAVCastControllerCallback()28 NapiAVCastControllerCallback::NapiAVCastControllerCallback()
29 {
30 SLOGI("construct");
31 }
32
~NapiAVCastControllerCallback()33 NapiAVCastControllerCallback::~NapiAVCastControllerCallback()
34 {
35 if (dataSrcRef_ != nullptr) {
36 napi_ref ref = dataSrcRef_;
37 dataSrcRef_ = nullptr;
38 napi_delete_reference(env_, ref);
39 }
40 SLOGI("destroy");
41 }
42
HandleEvent(int32_t event)43 void NapiAVCastControllerCallback::HandleEvent(int32_t event)
44 {
45 std::lock_guard<std::mutex> lockGuard(lock_);
46 if (callbacks_[event].empty()) {
47 SLOGE("not register callback event=%{public}d", event);
48 return;
49 }
50 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
51 asyncCallback_->Call(*ref);
52 }
53 }
54
CheckCallbackValid(int32_t event,const std::list<napi_ref>::iterator & ref)55 std::function<bool()> NapiAVCastControllerCallback::CheckCallbackValid(int32_t event,
56 const std::list<napi_ref>::iterator& ref)
57 {
58 return [this, event, ref]() {
59 std::lock_guard<std::mutex> lockGuard(lock_);
60 if (callbacks_[event].empty()) {
61 SLOGE("checkCallbackValid with empty list for event %{public}d", event);
62 return false;
63 }
64 bool hasFunc = false;
65 for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) {
66 hasFunc = (ref == it ? true : hasFunc);
67 }
68 SLOGD("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event);
69 return hasFunc;
70 };
71 }
72
73 template<typename T>
HandleEvent(int32_t event,const T & param)74 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const T& param)
75 {
76 std::lock_guard<std::mutex> lockGuard(lock_);
77 if (callbacks_[event].empty()) {
78 SLOGE("not register callback event=%{public}d", event);
79 return;
80 }
81 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
82 SLOGI("call with flag for event %{public}d", event);
83 asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
84 [param](napi_env env, int& argc, napi_value *argv) {
85 argc = NapiUtils::ARGC_ONE;
86 auto status = NapiUtils::SetValue(env, param, *argv);
87 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
88 });
89 }
90 }
91
92 template<typename T>
HandleEvent(int32_t event,const std::string & firstParam,const T & secondParam)93 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const std::string& firstParam, const T& secondParam)
94 {
95 std::lock_guard<std::mutex> lockGuard(lock_);
96 if (callbacks_[event].empty()) {
97 SLOGE("not register callback event=%{public}d", event);
98 return;
99 }
100 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
101 asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
102 [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
103 argc = NapiUtils::ARGC_TWO;
104 auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
105 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
106 status = NapiUtils::SetValue(env, secondParam, argv[1]);
107 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
108 });
109 }
110 }
111
112 template<typename T>
HandleEvent(int32_t event,const int32_t firstParam,const T & secondParam)113 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const int32_t firstParam, const T& secondParam)
114 {
115 std::lock_guard<std::mutex> lockGuard(lock_);
116 if (callbacks_[event].empty()) {
117 SLOGE("not register callback event=%{public}d", event);
118 return;
119 }
120 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
121 asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
122 [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
123 argc = NapiUtils::ARGC_TWO;
124 auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
125 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
126 status = NapiUtils::SetValue(env, secondParam, argv[1]);
127 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
128 });
129 }
130 }
131
HandleEvent(int32_t event,const int32_t firstParam,const int32_t secondParam,const int32_t thirdParam)132 void NapiAVCastControllerCallback::HandleEvent(int32_t event,
133 const int32_t firstParam, const int32_t secondParam, const int32_t thirdParam)
134 {
135 std::lock_guard<std::mutex> lockGuard(lock_);
136 if (callbacks_[event].empty()) {
137 SLOGE("not register callback event=%{public}d", event);
138 return;
139 }
140 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
141 asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
142 [firstParam, secondParam, thirdParam](napi_env env, int& argc, napi_value *argv) {
143 argc = NapiUtils::ARGC_THREE;
144 auto status = NapiUtils::SetValue(env, firstParam, argv[NapiUtils::ARGV_FIRST]);
145 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
146 status = NapiUtils::SetValue(env, secondParam, argv[NapiUtils::ARGV_SECOND]);
147 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
148 status = NapiUtils::SetValue(env, thirdParam, argv[NapiUtils::ARGV_THIRD]);
149 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
150 });
151 }
152 }
153
HandleErrorEvent(int32_t event,const int32_t errorCode,const std::string & errorMsg)154 void NapiAVCastControllerCallback::HandleErrorEvent(int32_t event, const int32_t errorCode,
155 const std::string& errorMsg)
156 {
157 std::lock_guard<std::mutex> lockGuard(lock_);
158 if (callbacks_[event].empty()) {
159 SLOGE("not register callback event=%{public}d", event);
160 return;
161 }
162 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
163 asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
164 [errorCode, errorMsg](napi_env env, int& argc, napi_value *argv) {
165 napi_status status = napi_create_object(env, argv);
166 CHECK_RETURN_VOID((status == napi_ok) && (argv != nullptr), "create object failed");
167
168 napi_value property = nullptr;
169 status = NapiUtils::SetValue(env, errorCode, property);
170 CHECK_RETURN_VOID((status == napi_ok) && (property != nullptr), "create property failed");
171 status = napi_set_named_property(env, *argv, "code", property);
172 CHECK_RETURN_VOID(status == napi_ok, "napi_set_named_property failed");
173
174 status = NapiUtils::SetValue(env, errorMsg, property);
175 CHECK_RETURN_VOID((status == napi_ok) && (property != nullptr), "create property failed");
176 status = napi_set_named_property(env, *argv, "message", property);
177 CHECK_RETURN_VOID(status == napi_ok, "napi_set_named_property failed");
178 });
179 }
180 }
181
OnCastPlaybackStateChange(const AVPlaybackState & state)182 void NapiAVCastControllerCallback::OnCastPlaybackStateChange(const AVPlaybackState& state)
183 {
184 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnCastPlaybackStateChange");
185 SLOGI("Start handle OnCastPlaybackStateChange event with state: %{public}d", state.GetState());
186 HandleEvent(EVENT_CAST_PLAYBACK_STATE_CHANGE, state);
187 }
188
OnMediaItemChange(const AVQueueItem & avQueueItem)189 void NapiAVCastControllerCallback::OnMediaItemChange(const AVQueueItem& avQueueItem)
190 {
191 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnMediaItemChange");
192 SLOGI("Start handle OnMediaItemChange event");
193 HandleEvent(EVENT_CAST_MEDIA_ITEM_CHANGE, avQueueItem);
194 }
195
OnPlayNext()196 void NapiAVCastControllerCallback::OnPlayNext()
197 {
198 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayNext");
199 SLOGI("Start handle OnPlayNext event");
200 HandleEvent(EVENT_CAST_PLAY_NEXT);
201 }
202
OnPlayPrevious()203 void NapiAVCastControllerCallback::OnPlayPrevious()
204 {
205 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayPrevious");
206 SLOGI("Start handle OnPlayPrevious event");
207 HandleEvent(EVENT_CAST_PLAY_PREVIOUS);
208 }
209
OnSeekDone(const int32_t seekNumber)210 void NapiAVCastControllerCallback::OnSeekDone(const int32_t seekNumber)
211 {
212 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnSeekDone");
213 SLOGI("Start handle OnSeekDone event");
214 HandleEvent(EVENT_CAST_SEEK_DONE, seekNumber);
215 }
216
OnVideoSizeChange(const int32_t width,const int32_t height)217 void NapiAVCastControllerCallback::OnVideoSizeChange(const int32_t width, const int32_t height)
218 {
219 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnVideoSizeChange");
220 SLOGI("Start handle OnVideoSizeChange event");
221 HandleEvent(EVENT_CAST_VIDEO_SIZE_CHANGE, width, height);
222 }
223
HandlePlayerErrorAPI13(const int32_t errorCode,const std::string & errorMsg)224 void NapiAVCastControllerCallback::HandlePlayerErrorAPI13(const int32_t errorCode, const std::string& errorMsg)
225 {
226 CastExtErrCodeAPI13 jsErr;
227 if (CAST_GENERIC_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
228 CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
229 // Generic error
230 jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
231 SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
232 HandleErrorEvent(EVENT_CAST_GENERIC_ERR, static_cast<int32_t>(jsErr), errorMsg);
233 } else if (CAST_IO_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
234 CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
235 // Input/Output errors
236 jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
237 SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
238 HandleErrorEvent(EVENT_CAST_IO_ERR, static_cast<int32_t>(jsErr), errorMsg);
239 } else if (CAST_PARSING_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
240 CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
241 // Content parsing errors
242 jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
243 SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
244 HandleErrorEvent(EVENT_CAST_PARSING_ERR, static_cast<int32_t>(jsErr), errorMsg);
245 } else if (CAST_DECODE_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
246 CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
247 // Decoding errors
248 jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
249 SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
250 HandleErrorEvent(EVENT_CAST_DECOD_EERR, static_cast<int32_t>(jsErr), errorMsg);
251 } else if (CAST_RENDER_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
252 CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
253 // AudioRender errors
254 jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
255 SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
256 HandleErrorEvent(EVENT_CAST_RENDER_ERR, static_cast<int32_t>(jsErr), errorMsg);
257 } else if (CAST_DRM_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
258 CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
259 // DRM errors
260 jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
261 SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
262 HandleErrorEvent(EVENT_CAST_DRM_ERR, static_cast<int32_t>(jsErr), errorMsg);
263 } else {
264 SLOGW("Can not match error code, use default");
265 // If error not in map, need add error and should not return default ERROR_CODE_UNSPECIFIED.
266 jsErr = CAST_GENERICERR_EXT_API13_UNSPECIFIED;
267 SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
268 HandleErrorEvent(EVENT_CAST_GENERIC_ERR, static_cast<int32_t>(jsErr), errorMsg);
269 }
270 }
271
OnPlayerError(const int32_t errorCode,const std::string & errorMsg)272 void NapiAVCastControllerCallback::OnPlayerError(const int32_t errorCode, const std::string& errorMsg)
273 {
274 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayerError");
275 SLOGI("Start handle OnPlayerError event");
276 if (static_cast<MediaServiceErrCode>(errorCode) >= MSERR_NO_MEMORY &&
277 static_cast<MediaServiceErrCode>(errorCode) <= MSERR_EXTEND_START) {
278 MediaServiceExtErrCodeAPI9 jsErr;
279 if (MSERRCODE_INFOS.count(static_cast<MediaServiceErrCode>(errorCode)) != 0 &&
280 MSERRCODE_TO_EXTERRORCODEAPI9.count(static_cast<MediaServiceErrCode>(errorCode)) != 0) {
281 jsErr = MSERRCODE_TO_EXTERRORCODEAPI9.at(static_cast<MediaServiceErrCode>(errorCode));
282 } else {
283 SLOGW("Can not match error code, use default");
284 // If error not in map, need add error and should not return default MSERR_EXT_API9_IO.
285 jsErr = MSERR_EXT_API9_IO;
286 }
287 SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
288 HandleErrorEvent(EVENT_CAST_ERROR, static_cast<int32_t>(jsErr), errorMsg);
289 } else {
290 HandlePlayerErrorAPI13(errorCode, errorMsg);
291 }
292 }
293
OnEndOfStream(const int32_t isLooping)294 void NapiAVCastControllerCallback::OnEndOfStream(const int32_t isLooping)
295 {
296 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnEndOfStream");
297 SLOGI("Start handle OnEndOfStream event");
298 HandleEvent(EVENT_CAST_END_OF_STREAM, isLooping);
299 }
300
OnPlayRequest(const AVQueueItem & avQueueItem)301 void NapiAVCastControllerCallback::OnPlayRequest(const AVQueueItem& avQueueItem)
302 {
303 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayRequest");
304 SLOGI("Start handle OnPlayRequest event");
305 HandleEvent(EVENT_CAST_PLAY_REQUEST, avQueueItem);
306 }
307
OnKeyRequest(const std::string & assetId,const std::vector<uint8_t> & keyRequestData)308 void NapiAVCastControllerCallback::OnKeyRequest(const std::string &assetId, const std::vector<uint8_t> &keyRequestData)
309 {
310 AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnKeyRequest");
311 SLOGI("Start handle OnKeyRequest event");
312 HandleEvent(EVENT_CAST_KEY_REQUEST, assetId, keyRequestData);
313 }
314
OnCastValidCommandChanged(const std::vector<int32_t> & cmds)315 void NapiAVCastControllerCallback::OnCastValidCommandChanged(const std::vector<int32_t>& cmds)
316 {
317 SLOGI("Start handle OnValidCommandChanged event. cmd size:%{public}zd", cmds.size());
318 std::vector<std::string> stringCmds = NapiCastControlCommand::ConvertCommands(cmds);
319 HandleEvent(EVENT_CAST_VALID_COMMAND_CHANGED, stringCmds);
320 }
321
onDataSrcRead(std::shared_ptr<AVSharedMemory> mem,uint32_t length,int64_t pos)322 int32_t NapiAVCastControllerCallback::onDataSrcRead(std::shared_ptr<AVSharedMemory> mem, uint32_t length, int64_t pos)
323 {
324 SLOGI("napi onDataSrcRead length %{public}d", length);
325 return readDataSrc(env_, mem, length, pos);
326 }
327
saveDataSrc(napi_env env,napi_value avQueueItem)328 napi_status NapiAVCastControllerCallback::saveDataSrc(napi_env env, napi_value avQueueItem)
329 {
330 napi_value fileSize;
331 napi_value callback {};
332 napi_status status = NapiQueueItem::GetDataSrc(env, avQueueItem, &fileSize, &callback);
333 CHECK_RETURN(status == napi_ok, "GetDataSrc value failed", status);
334 if (status != napi_ok) {
335 SLOGI("no saveDataSrc, reset");
336 return status;
337 }
338
339 napi_env preEnv = env_;
340 env_ = env;
341 if (dataSrcRef_ != nullptr) {
342 napi_ref ref = dataSrcRef_;
343 dataSrcRef_ = nullptr;
344 napi_delete_reference(preEnv, ref);
345 }
346 status = napi_create_reference(env, callback, 1, &dataSrcRef_);
347 CHECK_RETURN(status == napi_ok, "napi_create_reference failed", status);
348
349 if (threadSafeReadDataSrcFunc_ == nullptr) {
350 napi_value resourceName = nullptr;
351 napi_create_string_utf8(env, "ThreadSafeFunction in NapiAVCastControllerCallback",
352 NAPI_AUTO_LENGTH, &resourceName);
353 napi_create_threadsafe_function(env, nullptr, nullptr, resourceName, 0, 1, nullptr, nullptr,
354 nullptr, threadSafeReadDataSrcCb, &threadSafeReadDataSrcFunc_);
355 }
356 return napi_ok;
357 }
358
threadSafeReadDataSrcCb(napi_env env,napi_value js_cb,void * context,void * data)359 void NapiAVCastControllerCallback::threadSafeReadDataSrcCb(napi_env env, napi_value js_cb, void* context, void* data)
360 {
361 std::shared_ptr<DataContextForThreadSafe> appData(static_cast<DataContextForThreadSafe*>(data),
362 [](DataContextForThreadSafe* ptr) {
363 delete ptr;
364 ptr = nullptr;
365 });
366
367 napi_status status;
368 napi_value global {};
369 napi_get_global(env, &global);
370
371 napi_value callback {};
372 napi_get_reference_value(env, appData->callback, &callback);
373
374 napi_value argv[3] = { nullptr };
375
376 status = napi_create_external_arraybuffer(env, appData->buffer, appData->length,
377 [](napi_env env, void *data, void *hint) {}, nullptr, &argv[NapiUtils::ARGV_FIRST]);
378 CHECK_RETURN_VOID(status == napi_ok, "get napi_create_external_arraybuffer value failed");
379
380 status = napi_create_uint32(env, appData->length, &argv[NapiUtils::ARGV_SECOND]);
381 CHECK_RETURN_VOID(status == napi_ok, "get napi_create_uint32 value failed");
382
383 status = napi_create_int64(env, appData->pos, &argv[NapiUtils::ARGV_THIRD]);
384 CHECK_RETURN_VOID(status == napi_ok, "get napi_create_int64 value failed");
385
386 napi_value result;
387 status = napi_call_function(env, global, callback, NapiUtils::ARGC_THREE, argv, &result);
388 if (status != napi_ok) {
389 SLOGE("call function failed status=%{public}d.", status);
390 }
391 napi_get_value_int32(env, result, appData->result);
392
393 appData->dataSrcSyncCond.notify_one();
394 return;
395 }
396
readDataSrc(napi_env env,std::shared_ptr<AVSharedMemory> mem,uint32_t length,int64_t pos)397 int32_t NapiAVCastControllerCallback::readDataSrc(napi_env env, std::shared_ptr<AVSharedMemory> mem,
398 uint32_t length, int64_t pos)
399 {
400 if (dataSrcRef_ == nullptr) {
401 SLOGE("dataSrcRef_ nullptr");
402 return 0;
403 }
404 int32_t result;
405 DataContextForThreadSafe* data =
406 new DataContextForThreadSafe { dataSrcRef_, mem->GetBase(), length, pos, &result, dataSrcSyncCond_ };
407 napi_status status = napi_call_threadsafe_function(threadSafeReadDataSrcFunc_, data, napi_tsfn_blocking);
408 CHECK_RETURN(status == napi_ok, "get callback value failed", 0);
409
410 std::unique_lock<std::mutex> lock(dataSrcSyncLock_);
411 auto waitStatus = dataSrcSyncCond_.wait_for(lock, std::chrono::milliseconds(500));
412 if (waitStatus == std::cv_status::timeout) {
413 SLOGE("readDataSrc dataSrcSyncCond_ timeout");
414 }
415 SLOGI("readDataSrc result %{public}d", result);
416 return result;
417 }
418
AddCallback(napi_env env,int32_t event,napi_value callback)419 napi_status NapiAVCastControllerCallback::AddCallback(napi_env env, int32_t event, napi_value callback)
420 {
421 std::lock_guard<std::mutex> lockGuard(lock_);
422 napi_ref ref = nullptr;
423
424 CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
425 napi_generic_failure, "get callback reference failed");
426 CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
427 napi_status status = napi_create_reference(env, callback, NapiUtils::ARGC_ONE, &ref);
428 if (status != napi_ok) {
429 SLOGE("napi_create_reference failed");
430 return status;
431 }
432 if (asyncCallback_ == nullptr) {
433 asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
434 if (asyncCallback_ == nullptr) {
435 SLOGE("no memory");
436 return napi_generic_failure;
437 }
438 }
439 SLOGI("addCallback isValidSet to prevent off, with ref %{public}d", event);
440 callbacks_[event].push_back(ref);
441 if (isValid_ == nullptr) {
442 SLOGI("addCallback with no isValid_ init");
443 isValid_ = std::make_shared<bool>(true);
444 } else {
445 SLOGI("addCallback with isValid_ set true");
446 *isValid_ = true;
447 }
448 return napi_ok;
449 }
450
RemoveCallback(napi_env env,int32_t event,napi_value callback)451 napi_status NapiAVCastControllerCallback::RemoveCallback(napi_env env, int32_t event, napi_value callback)
452 {
453 std::lock_guard<std::mutex> lockGuard(lock_);
454 SLOGI("try remove callback for event %{public}d", event);
455 if (callback == nullptr) {
456 SLOGD("Remove callback, the callback is nullptr");
457 for (auto callbackRef = callbacks_[event].begin(); callbackRef != callbacks_[event].end(); ++callbackRef) {
458 napi_status ret = napi_delete_reference(env, *callbackRef);
459 CHECK_AND_RETURN_RET_LOG(ret == napi_ok, ret, "delete callback reference failed");
460 *callbackRef = nullptr;
461 }
462 callbacks_[event].clear();
463 // not remove this logic for play button will not valid when stopcast at media control second page
464 SLOGE("RemoveCallback with isvalid set false when playbackstatechange off");
465 if (event == EVENT_CAST_PLAYBACK_STATE_CHANGE) {
466 if (isValid_ == nullptr) {
467 SLOGE("remove callback with no isValid_ init");
468 return napi_ok;
469 }
470 SLOGI("removeCallback with isValid_ set false");
471 *isValid_ = false;
472 }
473 return napi_ok;
474 }
475 napi_ref ref = nullptr;
476 CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
477 napi_generic_failure, "get callback reference failed");
478 SLOGI("remove single callback with ref %{public}d", event);
479 CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
480 callbacks_[event].remove(ref);
481 return napi_delete_reference(env, ref);
482 }
483
IsCallbacksEmpty(int32_t event)484 bool NapiAVCastControllerCallback::IsCallbacksEmpty(int32_t event)
485 {
486 return callbacks_[event].empty();
487 }
488 } // namespace OHOS::AVSession
489