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_PLAYER, "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 delete cb;
161 return;
162 }
163
164 MEDIA_LOGD("OnBufferingUpdateCb is called, buffering type: %{public}d value: %{public}d", bufferingType, value);
165
166 cb->valueVec.push_back(bufferingType);
167 cb->valueVec.push_back(value);
168 return OnJsCallBackIntVec(cb);
169 }
170
OnEosCb(int32_t isLooping) const171 void PlayerCallbackNapi::OnEosCb(int32_t isLooping) const
172 {
173 MEDIA_LOGD("OnEndOfStream is called, isloop: %{public}d", isLooping);
174 }
175
OnStateChangeCb(PlayerStates state)176 void PlayerCallbackNapi::OnStateChangeCb(PlayerStates state)
177 {
178 MEDIA_LOGD("OnStateChanged is called, current state: %{public}d", state);
179 currentState_ = state;
180
181 std::string callbackName = "unknown";
182 switch (state) {
183 case PLAYER_PREPARED:
184 callbackName = DATA_LOAD_CALLBACK_NAME;
185 break;
186 case PLAYER_STARTED:
187 callbackName = PLAY_CALLBACK_NAME;
188 break;
189 case PLAYER_PAUSED:
190 callbackName = PAUSE_CALLBACK_NAME;
191 break;
192 case PLAYER_STOPPED:
193 callbackName = STOP_CALLBACK_NAME;
194 break;
195 case PLAYER_IDLE:
196 callbackName = RESET_CALLBACK_NAME;
197 break;
198 case PLAYER_PLAYBACK_COMPLETE:
199 callbackName = FINISH_CALLBACK_NAME;
200 break;
201 default:
202 callbackName = "unknown";
203 break;
204 }
205
206 if (refMap_.find(callbackName) == refMap_.end()) {
207 MEDIA_LOGW("can not find %{public}s callback!", callbackName.c_str());
208 return;
209 }
210
211 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
212 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
213 cb->callback = refMap_.at(callbackName);
214 cb->callbackName = callbackName;
215 return OnJsCallBack(cb);
216 }
217
OnPositionUpdateCb(int32_t position) const218 void PlayerCallbackNapi::OnPositionUpdateCb(int32_t position) const
219 {
220 MEDIA_LOGD("OnPositionUpdateCb is called, position: %{public}d", position);
221 if (refMap_.find(TIME_UPDATE_CALLBACK_NAME) == refMap_.end()) {
222 MEDIA_LOGW("can not find timeupdate callback!");
223 return;
224 }
225
226 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
227 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
228 cb->callback = refMap_.at(TIME_UPDATE_CALLBACK_NAME);
229 cb->callbackName = TIME_UPDATE_CALLBACK_NAME;
230 cb->valueVec.push_back(position);
231 return OnJsCallBackInt(cb);
232 }
233
OnMessageCb(int32_t type) const234 void PlayerCallbackNapi::OnMessageCb(int32_t type) const
235 {
236 MEDIA_LOGD("OnMessageCb is called, type: %{public}d", type);
237 }
238
OnVolumeChangeCb()239 void PlayerCallbackNapi::OnVolumeChangeCb()
240 {
241 MEDIA_LOGD("OnVolumeChangeCb in");
242 if (refMap_.find(VOL_CHANGE_CALLBACK_NAME) == refMap_.end()) {
243 MEDIA_LOGW("can not find vol change callback!");
244 return;
245 }
246 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
247 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
248 cb->callback = refMap_.at(VOL_CHANGE_CALLBACK_NAME);
249 cb->callbackName = VOL_CHANGE_CALLBACK_NAME;
250 return OnJsCallBack(cb);
251 }
252
OnAudioInterruptCb(const Format & infoBody) const253 void PlayerCallbackNapi::OnAudioInterruptCb(const Format &infoBody) const
254 {
255 MEDIA_LOGD("OnAudioInterruptCb in");
256 if (refMap_.find(AUDIO_INTERRUPT_CALLBACK_NAME) == refMap_.end()) {
257 MEDIA_LOGW("can not find audio interrupt callback!");
258 return;
259 }
260
261 PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
262 CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
263 cb->callback = refMap_.at(AUDIO_INTERRUPT_CALLBACK_NAME);
264 cb->callbackName = AUDIO_INTERRUPT_CALLBACK_NAME;
265 int32_t eventType = 0;
266 int32_t forceType = 0;
267 int32_t hintType = 0;
268 (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, eventType);
269 (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, forceType);
270 (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, hintType);
271 cb->interruptEvent.eventType = AudioStandard::InterruptType(eventType);
272 cb->interruptEvent.forceType = AudioStandard::InterruptForceType(forceType);
273 cb->interruptEvent.hintType = AudioStandard::InterruptHint(hintType);
274 return OnJsCallBackInterrupt(cb);
275 }
276
OnJsCallBack(PlayerJsCallback * jsCb) const277 void PlayerCallbackNapi::OnJsCallBack(PlayerJsCallback *jsCb) const
278 {
279 auto task = [event = jsCb]() {
280 // Js Thread
281 std::string request = event->callbackName;
282 MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
283 do {
284 std::shared_ptr<AutoRef> ref = event->callback.lock();
285 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
286
287 napi_handle_scope scope = nullptr;
288 napi_open_handle_scope(ref->env_, &scope);
289 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
290 ON_SCOPE_EXIT(0) {
291 napi_close_handle_scope(ref->env_, scope);
292 };
293
294 napi_value jsCallback = nullptr;
295 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
296 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
297 "%{public}s get reference value fail", request.c_str());
298
299 // Call back function
300 napi_value result = nullptr;
301 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 0, nullptr, &result);
302 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
303 } while (0);
304 delete event;
305 };
306
307 auto ret = napi_send_event(env_, task, napi_eprio_high);
308 if (ret != napi_status::napi_ok) {
309 MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
310 delete jsCb;
311 }
312 }
313
OnJsCallBackError(PlayerJsCallback * jsCb) const314 void PlayerCallbackNapi::OnJsCallBackError(PlayerJsCallback *jsCb) const
315 {
316 ON_SCOPE_EXIT(0) {
317 delete jsCb;
318 };
319
320 auto task = [event = jsCb]() {
321 // Js Thread
322 std::string request = event->callbackName;
323 MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
324 do {
325 std::shared_ptr<AutoRef> ref = event->callback.lock();
326 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
327
328 napi_handle_scope scope = nullptr;
329 napi_open_handle_scope(ref->env_, &scope);
330 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
331 ON_SCOPE_EXIT(0) {
332 napi_close_handle_scope(ref->env_, scope);
333 };
334
335 napi_value jsCallback = nullptr;
336 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
337 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
338 request.c_str());
339
340 napi_value msgValStr = nullptr;
341 nstatus = napi_create_string_utf8(ref->env_, event->errorMsg.c_str(), NAPI_AUTO_LENGTH, &msgValStr);
342 CHECK_AND_BREAK_LOG(nstatus == napi_ok && msgValStr != nullptr, "create error message str fail");
343
344 napi_value args[1] = { nullptr };
345 nstatus = napi_create_error(ref->env_, nullptr, msgValStr, &args[0]);
346 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr, "create error callback fail");
347
348 nstatus = CommonNapi::FillErrorArgs(ref->env_, static_cast<int32_t>(event->errorCode), args[0]);
349 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "create error callback fail");
350
351 // Call back function
352 napi_value result = nullptr;
353 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
354 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
355 } while (0);
356 delete event;
357 };
358
359 auto ret = napi_send_event(env_, task, napi_eprio_high);
360 if (ret != napi_status::napi_ok) {
361 MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
362 delete jsCb;
363 }
364 CANCEL_SCOPE_EXIT_GUARD(0);
365 }
366
OnJsCallBackInt(PlayerJsCallback * jsCb) const367 void PlayerCallbackNapi::OnJsCallBackInt(PlayerJsCallback *jsCb) const
368 {
369 auto task = [event = jsCb]() {
370 // Js Thread
371 std::string request = event->callbackName;
372 MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
373 do {
374 std::shared_ptr<AutoRef> ref = event->callback.lock();
375 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
376
377 napi_handle_scope scope = nullptr;
378 napi_open_handle_scope(ref->env_, &scope);
379 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
380 ON_SCOPE_EXIT(0) {
381 napi_close_handle_scope(ref->env_, scope);
382 };
383
384 napi_value jsCallback = nullptr;
385 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
386 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
387 request.c_str());
388
389 CHECK_AND_BREAK_LOG(event->valueVec.size() == 1, "%{public}s get reference value fail", request.c_str());
390 // Call back function
391 napi_value args[1] = { nullptr };
392 nstatus = napi_create_int32(ref->env_, event->valueVec[0], &args[0]);
393 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
394 "%{public}s fail to create callback", request.c_str());
395
396 napi_value result = nullptr;
397 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
398 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call seekDone callback", request.c_str());
399 } while (0);
400 delete event;
401 };
402
403 auto ret = napi_send_event(env_, task, napi_eprio_high);
404 if (ret != napi_status::napi_ok) {
405 MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
406 delete jsCb;
407 }
408 }
409
OnJsCallBackIntVec(PlayerJsCallback * jsCb) const410 void PlayerCallbackNapi::OnJsCallBackIntVec(PlayerJsCallback *jsCb) const
411 {
412 ON_SCOPE_EXIT(0) {
413 delete jsCb;
414 };
415
416 auto task = [event = jsCb]() {
417 // Js Thread
418 std::string request = event->callbackName;
419 MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
420 do {
421 std::shared_ptr<AutoRef> ref = event->callback.lock();
422 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
423
424 napi_handle_scope scope = nullptr;
425 napi_open_handle_scope(ref->env_, &scope);
426 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
427 ON_SCOPE_EXIT(0) {
428 napi_close_handle_scope(ref->env_, scope);
429 };
430
431 napi_value jsCallback = nullptr;
432 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
433 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
434 request.c_str());
435
436 CHECK_AND_BREAK_LOG(event->valueVec.size() == 2, "%{public}s get reference value fail", request.c_str());
437 // Call back function
438 napi_value args[2] = { nullptr };
439 nstatus = napi_create_int32(ref->env_, event->valueVec[0], &args[0]);
440 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
441 "%{public}s fail to create callback", request.c_str());
442
443 nstatus = napi_create_int32(ref->env_, event->valueVec[1], &args[1]);
444 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[1] != nullptr,
445 "%{public}s fail to create callback", request.c_str());
446
447 const size_t argCount = 2;
448 napi_value result = nullptr;
449 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
450 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
451 } while (0);
452 delete event;
453 };
454
455 auto ret = napi_send_event(env_, task, napi_eprio_high);
456 if (ret != napi_status::napi_ok) {
457 MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
458 delete jsCb;
459 }
460 CANCEL_SCOPE_EXIT_GUARD(0);
461 }
462
OnJsCallBackIntArray(PlayerJsCallback * jsCb) const463 void PlayerCallbackNapi::OnJsCallBackIntArray(PlayerJsCallback *jsCb) const
464 {
465 auto task = [event = jsCb]() {
466 // Js Thread
467 std::string request = event->callbackName;
468 MEDIA_LOGD("JsCallBack %{public}s, size = %{public}zu", request.c_str(), event->valueVec.size());
469
470 do {
471 std::shared_ptr<AutoRef> ref = event->callback.lock();
472 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
473
474 napi_handle_scope scope = nullptr;
475 napi_open_handle_scope(ref->env_, &scope);
476 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
477 ON_SCOPE_EXIT(0) {
478 napi_close_handle_scope(ref->env_, scope);
479 };
480
481 napi_value jsCallback = nullptr;
482 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
483 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
484 "%{public}s failed call callback", request.c_str());
485
486 napi_value array = nullptr;
487 bool ret = CommonNapi::AddArrayInt(ref->env_, array, event->valueVec);
488 CHECK_AND_BREAK_LOG(ret == true, "%{public}s failed call callback", request.c_str());
489
490 napi_value result = nullptr;
491 napi_value args[1] = {array};
492 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
493 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
494 } while (0);
495 delete event;
496 };
497
498 auto ret = napi_send_event(env_, task, napi_eprio_high);
499 if (ret != napi_status::napi_ok) {
500 MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
501 delete jsCb;
502 }
503 }
504
OnJsCallBackInterrupt(PlayerJsCallback * jsCb) const505 void PlayerCallbackNapi::OnJsCallBackInterrupt(PlayerJsCallback *jsCb) const
506 {
507 ON_SCOPE_EXIT(0) {
508 delete jsCb;
509 };
510
511 auto task = [event = jsCb]() {
512 std::string request = event->callbackName;
513 MEDIA_LOGD("JsCallBack %{public}s", request.c_str());
514
515 do {
516 std::shared_ptr<AutoRef> ref = event->callback.lock();
517 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
518
519 napi_handle_scope scope = nullptr;
520 napi_open_handle_scope(ref->env_, &scope);
521 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
522 ON_SCOPE_EXIT(0) {
523 napi_close_handle_scope(ref->env_, scope);
524 };
525
526 napi_value jsCallback = nullptr;
527 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
528 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
529 "%{public}s failed call callback", request.c_str());
530
531 napi_value args[1] = {nullptr};
532 napi_create_object(ref->env_, &args[0]);
533 CommonNapi::SetPropertyInt32(ref->env_, args[0], "eventType",
534 static_cast<int32_t>(event->interruptEvent.eventType));
535 CommonNapi::SetPropertyInt32(ref->env_, args[0], "forceType",
536 static_cast<int32_t>(event->interruptEvent.forceType));
537 CommonNapi::SetPropertyInt32(ref->env_, args[0], "hintType",
538 static_cast<int32_t>(event->interruptEvent.hintType));
539
540 napi_value result = nullptr;
541 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
542 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
543 } while (0);
544 delete event;
545 };
546
547 auto ret = napi_send_event(env_, task, napi_eprio_high);
548 if (ret != napi_status::napi_ok) {
549 MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
550 delete jsCb;
551 }
552 CANCEL_SCOPE_EXIT_GUARD(0);
553 }
554 } // namespace Media
555 } // namespace OHOS
556