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