• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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