1 /*
2 * Copyright (C) 2021 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 "player_callback_napi.h"
17 #include <uv.h>
18 #include "media_errors.h"
19 #include "media_log.h"
20 #include "scope_guard.h"
21
22 namespace {
23 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PlayerCallbackNapi"};
24 const std::string PLAY_CALLBACK_NAME = "play";
25 const std::string PAUSE_CALLBACK_NAME = "pause";
26 const std::string STOP_CALLBACK_NAME = "stop";
27 const std::string RESET_CALLBACK_NAME = "reset";
28 const std::string DATA_LOAD_CALLBACK_NAME = "dataLoad";
29 const std::string FINISH_CALLBACK_NAME = "finish";
30 const std::string TIME_UPDATE_CALLBACK_NAME = "timeUpdate";
31 const std::string ERROR_CALLBACK_NAME = "error";
32 const std::string VOL_CHANGE_CALLBACK_NAME = "volumeChange";
33 const std::string BUFFERING_UPDATE_CALLBACK_NAME = "bufferingUpdate";
34 const std::string AUDIO_INTERRUPT_CALLBACK_NAME = "audioInterrupt";
35 }
36
37 namespace OHOS {
38 namespace Media {
PlayerCallbackNapi(napi_env env)39 PlayerCallbackNapi::PlayerCallbackNapi(napi_env env)
40 : env_(env)
41 {
42 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
43 }
44
~PlayerCallbackNapi()45 PlayerCallbackNapi::~PlayerCallbackNapi()
46 {
47 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
48 }
49
SaveCallbackReference(const std::string & name,std::weak_ptr<AutoRef> ref)50 void PlayerCallbackNapi::SaveCallbackReference(const std::string &name, std::weak_ptr<AutoRef> ref)
51 {
52 std::lock_guard<std::mutex> lock(mutex_);
53 refMap_[name] = ref;
54 }
55
ClearCallbackReference()56 void PlayerCallbackNapi::ClearCallbackReference()
57 {
58 std::lock_guard<std::mutex> lock(mutex_);
59 refMap_.clear();
60 }
61
SendErrorCallback(MediaServiceExtErrCode errCode,const std::string & info)62 void PlayerCallbackNapi::SendErrorCallback(MediaServiceExtErrCode errCode, const std::string &info)
63 {
64 MEDIA_LOGE("in ErrorCallback: %{public}s", info.c_str());
65 std::lock_guard<std::mutex> lock(mutex_);
66 if (refMap_.find(ERROR_CALLBACK_NAME) == refMap_.end()) {
67 MEDIA_LOGW("can not find error callback!");
68 return;
69 }
70
71 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
72 CHECK_AND_RETURN_LOG(cb != nullptr, "cb is nullptr");
73
74 cb->callback = refMap_.at(ERROR_CALLBACK_NAME);
75 cb->callbackName = ERROR_CALLBACK_NAME;
76 cb->errorMsg = info;
77 cb->errorCode = errCode;
78 return OnJsCallBackError(cb);
79 }
80
GetCurrentState() const81 PlayerStates PlayerCallbackNapi::GetCurrentState() const
82 {
83 return currentState_;
84 }
85
OnError(int32_t errorCode,const std::string & errorMsg)86 void PlayerCallbackNapi::OnError(int32_t errorCode, const std::string &errorMsg)
87 {
88 MEDIA_LOGE("OnErrorCb:errorCode %{public}d, errorMsg %{public}s", errorCode, errorMsg.c_str());
89 MediaServiceExtErrCode err = MSErrorToExtError(static_cast<MediaServiceErrCode>(errorCode));
90 return SendErrorCallback(err, errorMsg);
91 }
92
OnInfo(PlayerOnInfoType type,int32_t extra,const Format & infoBody)93 void PlayerCallbackNapi::OnInfo(PlayerOnInfoType type, int32_t extra, const Format &infoBody)
94 {
95 std::lock_guard<std::mutex> lock(mutex_);
96 MEDIA_LOGI("OnInfo is called, PlayerOnInfoType: %{public}d", type);
97 switch (type) {
98 case INFO_TYPE_SEEKDONE:
99 OnSeekDoneCb(extra);
100 break;
101 case INFO_TYPE_EOS:
102 OnEosCb(extra);
103 break;
104 case INFO_TYPE_STATE_CHANGE:
105 OnStateChangeCb(static_cast<PlayerStates>(extra));
106 break;
107 case INFO_TYPE_POSITION_UPDATE:
108 OnPositionUpdateCb(extra);
109 break;
110 case INFO_TYPE_MESSAGE:
111 OnMessageCb(extra);
112 break;
113 case INFO_TYPE_VOLUME_CHANGE:
114 OnVolumeChangeCb();
115 break;
116 case INFO_TYPE_BUFFERING_UPDATE:
117 OnBufferingUpdateCb(infoBody);
118 break;
119 case INFO_TYPE_INTERRUPT_EVENT:
120 OnAudioInterruptCb(infoBody);
121 break;
122 default:
123 break;
124 }
125 MEDIA_LOGD("send OnInfo callback success");
126 }
127
OnSeekDoneCb(int32_t currentPositon) const128 void PlayerCallbackNapi::OnSeekDoneCb(int32_t currentPositon) const
129 {
130 MEDIA_LOGD("OnSeekDone is called, currentPositon: %{public}d", currentPositon);
131 }
132
OnBufferingUpdateCb(const Format & infoBody) const133 void PlayerCallbackNapi::OnBufferingUpdateCb(const Format &infoBody) const
134 {
135 if (refMap_.find(BUFFERING_UPDATE_CALLBACK_NAME) == refMap_.end()) {
136 MEDIA_LOGW("can not find buffering update callback!");
137 return;
138 }
139
140 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
141 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
142 cb->callback = refMap_.at(BUFFERING_UPDATE_CALLBACK_NAME);
143 cb->callbackName = BUFFERING_UPDATE_CALLBACK_NAME;
144
145 int32_t value = 0;
146 int32_t bufferingType = -1;
147 if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_START))) {
148 bufferingType = BUFFERING_START;
149 (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_START), value);
150 } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_END))) {
151 bufferingType = BUFFERING_END;
152 (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_END), value);
153 } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT))) {
154 bufferingType = BUFFERING_PERCENT;
155 (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT), value);
156 } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_CACHED_DURATION))) {
157 bufferingType = CACHED_DURATION;
158 (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_CACHED_DURATION), value);
159 } else {
160 return;
161 }
162
163 MEDIA_LOGD("OnBufferingUpdateCb is called, buffering type: %{public}d value: %{public}d", bufferingType, value);
164
165 cb->valueVec.push_back(bufferingType);
166 cb->valueVec.push_back(value);
167 return OnJsCallBackIntVec(cb);
168 }
169
OnEosCb(int32_t isLooping) const170 void PlayerCallbackNapi::OnEosCb(int32_t isLooping) const
171 {
172 MEDIA_LOGD("OnEndOfStream is called, isloop: %{public}d", isLooping);
173 }
174
OnStateChangeCb(PlayerStates state)175 void PlayerCallbackNapi::OnStateChangeCb(PlayerStates state)
176 {
177 MEDIA_LOGD("OnStateChanged is called, current state: %{public}d", state);
178 currentState_ = state;
179
180 std::string callbackName = "unknown";
181 switch (state) {
182 case PLAYER_PREPARED:
183 callbackName = DATA_LOAD_CALLBACK_NAME;
184 break;
185 case PLAYER_STARTED:
186 callbackName = PLAY_CALLBACK_NAME;
187 break;
188 case PLAYER_PAUSED:
189 callbackName = PAUSE_CALLBACK_NAME;
190 break;
191 case PLAYER_STOPPED:
192 callbackName = STOP_CALLBACK_NAME;
193 break;
194 case PLAYER_IDLE:
195 callbackName = RESET_CALLBACK_NAME;
196 break;
197 case PLAYER_PLAYBACK_COMPLETE:
198 callbackName = FINISH_CALLBACK_NAME;
199 break;
200 default:
201 callbackName = "unknown";
202 break;
203 }
204
205 if (refMap_.find(callbackName) == refMap_.end()) {
206 MEDIA_LOGW("can not find %{public}s callback!", callbackName.c_str());
207 return;
208 }
209
210 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
211 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
212 cb->callback = refMap_.at(callbackName);
213 cb->callbackName = callbackName;
214 return OnJsCallBack(cb);
215 }
216
OnPositionUpdateCb(int32_t position) const217 void PlayerCallbackNapi::OnPositionUpdateCb(int32_t position) const
218 {
219 MEDIA_LOGD("OnPositionUpdateCb is called, position: %{public}d", position);
220 if (refMap_.find(TIME_UPDATE_CALLBACK_NAME) == refMap_.end()) {
221 MEDIA_LOGW("can not find timeupdate callback!");
222 return;
223 }
224
225 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
226 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
227 cb->callback = refMap_.at(TIME_UPDATE_CALLBACK_NAME);
228 cb->callbackName = TIME_UPDATE_CALLBACK_NAME;
229 cb->valueVec.push_back(position);
230 return OnJsCallBackInt(cb);
231 }
232
OnMessageCb(int32_t type) const233 void PlayerCallbackNapi::OnMessageCb(int32_t type) const
234 {
235 MEDIA_LOGD("OnMessageCb is called, type: %{public}d", type);
236 }
237
OnVolumeChangeCb()238 void PlayerCallbackNapi::OnVolumeChangeCb()
239 {
240 MEDIA_LOGD("OnVolumeChangeCb in");
241 if (refMap_.find(VOL_CHANGE_CALLBACK_NAME) == refMap_.end()) {
242 MEDIA_LOGW("can not find vol change callback!");
243 return;
244 }
245 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
246 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
247 cb->callback = refMap_.at(VOL_CHANGE_CALLBACK_NAME);
248 cb->callbackName = VOL_CHANGE_CALLBACK_NAME;
249 return OnJsCallBack(cb);
250 }
251
OnAudioInterruptCb(const Format & infoBody) const252 void PlayerCallbackNapi::OnAudioInterruptCb(const Format &infoBody) const
253 {
254 MEDIA_LOGD("OnAudioInterruptCb in");
255 if (refMap_.find(AUDIO_INTERRUPT_CALLBACK_NAME) == refMap_.end()) {
256 MEDIA_LOGW("can not find audio interrupt callback!");
257 return;
258 }
259
260 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
261 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
262 cb->callback = refMap_.at(AUDIO_INTERRUPT_CALLBACK_NAME);
263 cb->callbackName = AUDIO_INTERRUPT_CALLBACK_NAME;
264 int32_t eventType = 0;
265 int32_t forceType = 0;
266 int32_t hintType = 0;
267 (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, eventType);
268 (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, forceType);
269 (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, hintType);
270 cb->interruptEvent.eventType = AudioStandard::InterruptType(eventType);
271 cb->interruptEvent.forceType = AudioStandard::InterruptForceType(forceType);
272 cb->interruptEvent.hintType = AudioStandard::InterruptHint(hintType);
273 return OnJsCallBackInterrupt(cb);
274 }
275
OnJsCallBack(PlayerJsCallback * jsCb) const276 void PlayerCallbackNapi::OnJsCallBack(PlayerJsCallback *jsCb) const
277 {
278 uv_loop_s *loop = nullptr;
279 napi_get_uv_event_loop(env_, &loop);
280 if (loop == nullptr) {
281 delete jsCb;
282 return;
283 }
284
285 uv_work_t *work = new(std::nothrow) uv_work_t;
286 if (work == nullptr) {
287 MEDIA_LOGE("No memory");
288 delete jsCb;
289 return;
290 }
291 work->data = reinterpret_cast<void *>(jsCb);
292
293 int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
294 // Js Thread
295 CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
296 PlayerJsCallback *event = reinterpret_cast<PlayerJsCallback *>(work->data);
297 std::string request = event->callbackName;
298 MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
299 do {
300 CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
301 std::shared_ptr<AutoRef> ref = event->callback.lock();
302 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
303
304 napi_handle_scope scope = nullptr;
305 napi_open_handle_scope(ref->env_, &scope);
306 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
307 ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
308
309 napi_value jsCallback = nullptr;
310 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
311 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
312 "%{public}s get reference value fail", request.c_str());
313
314 // Call back function
315 napi_value result = nullptr;
316 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 0, nullptr, &result);
317 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
318 } while (0);
319 delete event;
320 delete work;
321 });
322 if (ret != 0) {
323 MEDIA_LOGE("Failed to execute libuv work queue");
324 delete jsCb;
325 delete work;
326 }
327 }
328
OnJsCallBackError(PlayerJsCallback * jsCb) const329 void PlayerCallbackNapi::OnJsCallBackError(PlayerJsCallback *jsCb) const
330 {
331 uv_loop_s *loop = nullptr;
332 napi_get_uv_event_loop(env_, &loop);
333 if (loop == nullptr) {
334 delete jsCb;
335 return;
336 }
337
338 uv_work_t *work = new(std::nothrow) uv_work_t;
339 if (work == nullptr) {
340 MEDIA_LOGE("No memory");
341 delete jsCb;
342 return;
343 }
344 work->data = reinterpret_cast<void *>(jsCb);
345
346 int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
347 // Js Thread
348 CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
349 PlayerJsCallback *event = reinterpret_cast<PlayerJsCallback *>(work->data);
350 std::string request = event->callbackName;
351 MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
352 do {
353 CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
354 std::shared_ptr<AutoRef> ref = event->callback.lock();
355 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
356
357 napi_handle_scope scope = nullptr;
358 napi_open_handle_scope(ref->env_, &scope);
359 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
360 ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
361
362 napi_value jsCallback = nullptr;
363 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
364 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
365 request.c_str());
366
367 napi_value msgValStr = nullptr;
368 nstatus = napi_create_string_utf8(ref->env_, event->errorMsg.c_str(), NAPI_AUTO_LENGTH, &msgValStr);
369 CHECK_AND_RETURN_LOG(nstatus == napi_ok && msgValStr != nullptr, "create error message str fail");
370
371 napi_value args[1] = { nullptr };
372 nstatus = napi_create_error(ref->env_, nullptr, msgValStr, &args[0]);
373 CHECK_AND_RETURN_LOG(nstatus == napi_ok && args[0] != nullptr, "create error callback fail");
374
375 nstatus = CommonNapi::FillErrorArgs(ref->env_, static_cast<int32_t>(event->errorCode), args[0]);
376 CHECK_AND_RETURN_LOG(nstatus == napi_ok, "create error callback fail");
377
378 // Call back function
379 napi_value result = nullptr;
380 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
381 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
382 } while (0);
383 delete event;
384 delete work;
385 });
386 if (ret != 0) {
387 MEDIA_LOGE("Failed to execute libuv work queue");
388 delete jsCb;
389 delete work;
390 }
391 }
392
OnJsCallBackInt(PlayerJsCallback * jsCb) const393 void PlayerCallbackNapi::OnJsCallBackInt(PlayerJsCallback *jsCb) const
394 {
395 uv_loop_s *loop = nullptr;
396 napi_get_uv_event_loop(env_, &loop);
397 if (loop == nullptr) {
398 delete jsCb;
399 return;
400 }
401
402 uv_work_t *work = new(std::nothrow) uv_work_t;
403 if (work == nullptr) {
404 MEDIA_LOGE("No memory");
405 delete jsCb;
406 return;
407 }
408 work->data = reinterpret_cast<void *>(jsCb);
409
410 int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
411 // Js Thread
412 CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
413 PlayerJsCallback *event = reinterpret_cast<PlayerJsCallback *>(work->data);
414 std::string request = event->callbackName;
415 MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
416 do {
417 CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
418 std::shared_ptr<AutoRef> ref = event->callback.lock();
419 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
420
421 napi_handle_scope scope = nullptr;
422 napi_open_handle_scope(ref->env_, &scope);
423 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
424 ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
425
426 napi_value jsCallback = nullptr;
427 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
428 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
429 request.c_str());
430
431 CHECK_AND_BREAK_LOG(event->valueVec.size() == 1, "%{public}s get reference value fail", request.c_str());
432 // Call back function
433 napi_value args[1] = { nullptr };
434 nstatus = napi_create_int32(ref->env_, event->valueVec[0], &args[0]);
435 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
436 "%{public}s fail to create callback", request.c_str());
437
438 napi_value result = nullptr;
439 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
440 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call seekDone callback", request.c_str());
441 } while (0);
442 delete event;
443 delete work;
444 });
445 if (ret != 0) {
446 MEDIA_LOGE("Failed to execute libuv work queue");
447 delete jsCb;
448 delete work;
449 }
450 }
451
OnJsCallBackIntVec(PlayerJsCallback * jsCb) const452 void PlayerCallbackNapi::OnJsCallBackIntVec(PlayerJsCallback *jsCb) const
453 {
454 uv_loop_s *loop = nullptr;
455 napi_get_uv_event_loop(env_, &loop);
456 if (loop == nullptr) {
457 delete jsCb;
458 return;
459 }
460
461 uv_work_t *work = new(std::nothrow) uv_work_t;
462 if (work == nullptr) {
463 MEDIA_LOGE("No memory");
464 delete jsCb;
465 return;
466 }
467 work->data = reinterpret_cast<void *>(jsCb);
468
469 int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
470 // Js Thread
471 CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
472 PlayerJsCallback *event = reinterpret_cast<PlayerJsCallback *>(work->data);
473 std::string request = event->callbackName;
474 MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
475 do {
476 CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
477 std::shared_ptr<AutoRef> ref = event->callback.lock();
478 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
479
480 napi_handle_scope scope = nullptr;
481 napi_open_handle_scope(ref->env_, &scope);
482 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
483 ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
484
485 napi_value jsCallback = nullptr;
486 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
487 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
488 request.c_str());
489
490 CHECK_AND_BREAK_LOG(event->valueVec.size() == 2, "%{public}s get reference value fail", request.c_str());
491 // Call back function
492 napi_value args[2] = { nullptr };
493 nstatus = napi_create_int32(ref->env_, event->valueVec[0], &args[0]);
494 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
495 "%{public}s fail to create callback", request.c_str());
496
497 nstatus = napi_create_int32(ref->env_, event->valueVec[1], &args[1]);
498 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[1] != nullptr,
499 "%{public}s fail to create callback", request.c_str());
500
501 const size_t argCount = 2;
502 napi_value result = nullptr;
503 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
504 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
505 } while (0);
506 delete event;
507 delete work;
508 });
509 if (ret != 0) {
510 MEDIA_LOGE("Failed to execute libuv work queue");
511 delete jsCb;
512 delete work;
513 }
514 }
515
OnJsCallBackIntArray(PlayerJsCallback * jsCb) const516 void PlayerCallbackNapi::OnJsCallBackIntArray(PlayerJsCallback *jsCb) const
517 {
518 uv_loop_s *loop = nullptr;
519 napi_get_uv_event_loop(env_, &loop);
520 if (loop == nullptr) {
521 delete jsCb;
522 return;
523 }
524
525 uv_work_t *work = new(std::nothrow) uv_work_t;
526 if (work == nullptr) {
527 MEDIA_LOGE("No memory");
528 delete jsCb;
529 return;
530 }
531 work->data = reinterpret_cast<void *>(jsCb);
532
533 int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
534 // Js Thread
535 CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
536 PlayerJsCallback *event = reinterpret_cast<PlayerJsCallback *>(work->data);
537 std::string request = event->callbackName;
538 MEDIA_LOGD("JsCallBack %{public}s, size = %{public}zu", request.c_str(), event->valueVec.size());
539
540 do {
541 CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
542 std::shared_ptr<AutoRef> ref = event->callback.lock();
543 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
544
545 napi_handle_scope scope = nullptr;
546 napi_open_handle_scope(ref->env_, &scope);
547 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
548 ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
549
550 napi_value jsCallback = nullptr;
551 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
552 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
553 "%{public}s failed call callback", request.c_str());
554
555 napi_value array = nullptr;
556 bool ret = CommonNapi::AddArrayInt(ref->env_, array, event->valueVec);
557 CHECK_AND_BREAK_LOG(ret == true, "%{public}s failed call callback", request.c_str());
558
559 napi_value result = nullptr;
560 napi_value args[1] = {array};
561 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
562 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
563 } while (0);
564 delete event;
565 delete work;
566 });
567 if (ret != 0) {
568 MEDIA_LOGE("Failed to execute libuv work queue");
569 delete jsCb;
570 delete work;
571 }
572 }
573
OnJsCallBackInterrupt(PlayerJsCallback * jsCb) const574 void PlayerCallbackNapi::OnJsCallBackInterrupt(PlayerJsCallback *jsCb) const
575 {
576 uv_loop_s *loop = nullptr;
577 napi_get_uv_event_loop(env_, &loop);
578 if (loop == nullptr) {
579 delete jsCb;
580 return;
581 }
582
583 uv_work_t *work = new(std::nothrow) uv_work_t;
584 if (work == nullptr) {
585 delete jsCb;
586 return;
587 }
588 work->data = reinterpret_cast<void *>(jsCb);
589
590 int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
591 CHECK_AND_RETURN_LOG(work != nullptr, "work is nullptr");
592 PlayerJsCallback *event = reinterpret_cast<PlayerJsCallback *>(work->data);
593 std::string request = event->callbackName;
594 MEDIA_LOGD("JsCallBack %{public}s", request.c_str());
595
596 do {
597 CHECK_AND_BREAK_LOG(status != UV_ECANCELED, "%{public}s canceled", request.c_str());
598 std::shared_ptr<AutoRef> ref = event->callback.lock();
599 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
600
601 napi_handle_scope scope = nullptr;
602 napi_open_handle_scope(ref->env_, &scope);
603 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
604 ON_SCOPE_EXIT(0) { napi_close_handle_scope(ref->env_, scope); };
605
606 napi_value jsCallback = nullptr;
607 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
608 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
609 "%{public}s failed call callback", request.c_str());
610
611 napi_value args[1] = {nullptr};
612 napi_create_object(ref->env_, &args[0]);
613 CommonNapi::SetPropertyInt32(ref->env_, args[0], "eventType",
614 static_cast<int32_t>(event->interruptEvent.eventType));
615 CommonNapi::SetPropertyInt32(ref->env_, args[0], "forceType",
616 static_cast<int32_t>(event->interruptEvent.forceType));
617 CommonNapi::SetPropertyInt32(ref->env_, args[0], "hintType",
618 static_cast<int32_t>(event->interruptEvent.hintType));
619
620 napi_value result = nullptr;
621 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
622 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
623 } while (0);
624 delete event;
625 delete work;
626 });
627 if (ret != 0) {
628 MEDIA_LOGE("Failed to execute libuv work queue");
629 delete jsCb;
630 delete work;
631 }
632 }
633 } // namespace Media
634 } // namespace OHOS
635