• 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 #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