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 "audio_player_napi.h"
17 #include <climits>
18 #include "player_callback_napi.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "string_ex.h"
22
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioPlayerNapi"};
25 }
26
27 namespace OHOS {
28 namespace Media {
29 thread_local napi_ref AudioPlayerNapi::constructor_ = nullptr;
30 const std::string CLASS_NAME = "AudioPlayer";
31 const std::string STATE_PLAYING = "playing";
32 const std::string STATE_PAUSED = "paused";
33 const std::string STATE_STOPPED = "stopped";
34 const std::string STATE_IDLE = "idle";
35 const std::string STATE_ERROR = "error";
36
AudioPlayerNapi()37 AudioPlayerNapi::AudioPlayerNapi()
38 {
39 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
40 }
41
~AudioPlayerNapi()42 AudioPlayerNapi::~AudioPlayerNapi()
43 {
44 CancelCallback();
45 nativePlayer_ = nullptr;
46 callbackNapi_ = nullptr;
47
48 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
49 }
50
Init(napi_env env,napi_value exports)51 napi_value AudioPlayerNapi::Init(napi_env env, napi_value exports)
52 {
53 napi_property_descriptor properties[] = {
54 DECLARE_NAPI_FUNCTION("play", Play),
55 DECLARE_NAPI_FUNCTION("pause", Pause),
56 DECLARE_NAPI_FUNCTION("stop", Stop),
57 DECLARE_NAPI_FUNCTION("reset", Reset),
58 DECLARE_NAPI_FUNCTION("release", Release),
59 DECLARE_NAPI_FUNCTION("seek", Seek),
60 DECLARE_NAPI_FUNCTION("on", On),
61 DECLARE_NAPI_FUNCTION("setVolume", SetVolume),
62 DECLARE_NAPI_FUNCTION("getTrackDescription", GetTrackDescription),
63
64 DECLARE_NAPI_GETTER_SETTER("src", GetSrc, SetSrc),
65 DECLARE_NAPI_GETTER_SETTER("fdSrc", GetFdSrc, SetFdSrc),
66 DECLARE_NAPI_GETTER_SETTER("loop", GetLoop, SetLoop),
67 DECLARE_NAPI_GETTER_SETTER("audioInterruptMode", GetAudioInterruptMode, SetAudioInterruptMode),
68
69 DECLARE_NAPI_GETTER("currentTime", GetCurrentTime),
70 DECLARE_NAPI_GETTER("duration", GetDuration),
71 DECLARE_NAPI_GETTER("state", GetState)
72 };
73
74 napi_property_descriptor staticProperty[] = {
75 DECLARE_NAPI_STATIC_FUNCTION("createAudioPlayer", CreateAudioPlayer),
76 };
77
78 napi_value constructor = nullptr;
79 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
80 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
81 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AudioPlayer class");
82
83 status = napi_create_reference(env, constructor, 1, &constructor_);
84 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
85
86 status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
87 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
88
89 status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
90 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
91
92 MEDIA_LOGD("Init success");
93 return exports;
94 }
95
Constructor(napi_env env,napi_callback_info info)96 napi_value AudioPlayerNapi::Constructor(napi_env env, napi_callback_info info)
97 {
98 napi_value result = nullptr;
99 napi_value jsThis = nullptr;
100 size_t argCount = 0;
101 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
102 if (status != napi_ok) {
103 napi_get_undefined(env, &result);
104 MEDIA_LOGE("Failed to retrieve details about the callback");
105 return result;
106 }
107
108 AudioPlayerNapi *playerNapi = new(std::nothrow) AudioPlayerNapi();
109 CHECK_AND_RETURN_RET_LOG(playerNapi != nullptr, nullptr, "No memory");
110
111 playerNapi->env_ = env;
112 playerNapi->nativePlayer_ = PlayerFactory::CreatePlayer();
113 if (playerNapi->nativePlayer_ == nullptr) {
114 MEDIA_LOGE("failed to CreatePlayer");
115 }
116
117 if (playerNapi->callbackNapi_ == nullptr && playerNapi->nativePlayer_ != nullptr) {
118 playerNapi->callbackNapi_ = std::make_shared<PlayerCallbackNapi>(env);
119 (void)playerNapi->nativePlayer_->SetPlayerCallback(playerNapi->callbackNapi_);
120 }
121
122 status = napi_wrap(env, jsThis, reinterpret_cast<void *>(playerNapi),
123 AudioPlayerNapi::Destructor, nullptr, nullptr);
124 if (status != napi_ok) {
125 napi_get_undefined(env, &result);
126 delete playerNapi;
127 MEDIA_LOGE("Failed to wrap native instance");
128 return result;
129 }
130
131 MEDIA_LOGD("Constructor success");
132 return jsThis;
133 }
134
Destructor(napi_env env,void * nativeObject,void * finalize)135 void AudioPlayerNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
136 {
137 (void)env;
138 (void)finalize;
139 if (nativeObject != nullptr) {
140 delete reinterpret_cast<AudioPlayerNapi *>(nativeObject);
141 }
142 MEDIA_LOGD("Destructor success");
143 }
144
CreateAudioPlayer(napi_env env,napi_callback_info info)145 napi_value AudioPlayerNapi::CreateAudioPlayer(napi_env env, napi_callback_info info)
146 {
147 napi_value result = nullptr;
148 napi_value constructor = nullptr;
149 napi_status status = napi_get_reference_value(env, constructor_, &constructor);
150 if (status != napi_ok) {
151 MEDIA_LOGE("Failed to get the representation of constructor object");
152 napi_get_undefined(env, &result);
153 return result;
154 }
155
156 status = napi_new_instance(env, constructor, 0, nullptr, &result);
157 if (status != napi_ok) {
158 MEDIA_LOGE("Failed to instantiate JavaScript audio player instance");
159 napi_get_undefined(env, &result);
160 return result;
161 }
162
163 MEDIA_LOGD("CreateAudioPlayer success");
164 return result;
165 }
166
CreateAudioPlayerAsync(napi_env env,napi_callback_info info)167 napi_value AudioPlayerNapi::CreateAudioPlayerAsync(napi_env env, napi_callback_info info)
168 {
169 napi_value result = nullptr;
170 napi_get_undefined(env, &result);
171 MEDIA_LOGD("CreateAudioPlayerAsync In");
172
173 std::unique_ptr<MediaAsyncContext> asyncContext = std::make_unique<MediaAsyncContext>(env);
174
175 // get args
176 napi_value jsThis = nullptr;
177 napi_value args[1] = { nullptr };
178 size_t argCount = 1;
179 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
180 if (status != napi_ok) {
181 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
182 }
183
184 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
185 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
186 asyncContext->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
187 napi_value resource = nullptr;
188 napi_create_string_utf8(env, "CreateAudioPlayerAsync", NAPI_AUTO_LENGTH, &resource);
189 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
190 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncContext.get()), &asyncContext->work));
191 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
192 asyncContext.release();
193
194 return result;
195 }
196
SetSrc(napi_env env,napi_callback_info info)197 napi_value AudioPlayerNapi::SetSrc(napi_env env, napi_callback_info info)
198 {
199 napi_value undefinedResult = nullptr;
200 napi_get_undefined(env, &undefinedResult);
201 napi_value jsThis = nullptr;
202 napi_value args[1] = { nullptr };
203
204 size_t argCount = 1;
205 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
206 if (status != napi_ok || jsThis == nullptr || args[0] == nullptr) {
207 MEDIA_LOGE("Failed to retrieve details about the callback");
208 return undefinedResult;
209 }
210
211 AudioPlayerNapi *player = nullptr;
212 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
213 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
214
215 if (player->nativePlayer_ == nullptr) {
216 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
217 return undefinedResult;
218 }
219
220 napi_valuetype valueType = napi_undefined;
221 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_string) {
222 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
223 return undefinedResult;
224 }
225
226 player->uri_ = CommonNapi::GetStringArgument(env, args[0]);
227 const std::string fdHead = "fd://";
228 const std::string httpHead = "http";
229 int32_t ret = MSERR_EXT_INVALID_VAL;
230
231 MEDIA_LOGD("input url is %{public}s!", player->uri_.c_str());
232 if (player->uri_.find(fdHead) != std::string::npos) {
233 int32_t fd = -1;
234 std::string inputFd = player->uri_.substr(fdHead.size());
235 if (!StrToInt(inputFd, fd) || fd < 0) {
236 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
237 return undefinedResult;
238 }
239
240 ret = player->nativePlayer_->SetSource(fd, 0, -1);
241 } else if (player->uri_.find(httpHead) != std::string::npos) {
242 ret = player->nativePlayer_->SetSource(player->uri_);
243 }
244
245 if (ret != MSERR_OK) {
246 MEDIA_LOGE("input url error!");
247 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetSource");
248 return undefinedResult;
249 }
250
251 ret = player->nativePlayer_->PrepareAsync();
252 if (ret != MSERR_OK) {
253 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to PrepareAsync");
254 return undefinedResult;
255 }
256
257 MEDIA_LOGD("SetSrc success");
258 return undefinedResult;
259 }
260
GetSrc(napi_env env,napi_callback_info info)261 napi_value AudioPlayerNapi::GetSrc(napi_env env, napi_callback_info info)
262 {
263 napi_value undefinedResult = nullptr;
264 napi_get_undefined(env, &undefinedResult);
265 napi_value jsThis = nullptr;
266 napi_value jsResult = nullptr;
267 AudioPlayerNapi *player = nullptr;
268 size_t argCount = 0;
269
270 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
271 if (status != napi_ok || jsThis == nullptr) {
272 MEDIA_LOGE("Failed to retrieve details about the callback");
273 return undefinedResult;
274 }
275
276 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
277 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "get player napi error");
278
279 status = napi_create_string_utf8(env, player->uri_.c_str(), NAPI_AUTO_LENGTH, &jsResult);
280 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_string_utf8 error");
281
282 MEDIA_LOGD("GetSrc success");
283 return jsResult;
284 }
285
SetFdSrc(napi_env env,napi_callback_info info)286 napi_value AudioPlayerNapi::SetFdSrc(napi_env env, napi_callback_info info)
287 {
288 napi_value undefinedResult = nullptr;
289 napi_get_undefined(env, &undefinedResult);
290 napi_value jsThis = nullptr;
291 napi_value args[1] = { nullptr };
292
293 size_t argCount = 1;
294 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
295 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr && args[0] != nullptr,
296 undefinedResult, "Failed to retrieve details about the callback");
297
298 AudioPlayerNapi *player = nullptr;
299 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
300 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
301 if (player->nativePlayer_ == nullptr) {
302 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
303 return undefinedResult;
304 }
305
306 napi_valuetype valueType = napi_undefined;
307 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object) {
308 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
309 return undefinedResult;
310 }
311
312 if (!CommonNapi::GetFdArgument(env, args[0], player->rawFd_)) {
313 MEDIA_LOGE("get rawfd argument failed!");
314 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
315 return undefinedResult;
316 }
317
318 int32_t ret = player->nativePlayer_->SetSource(player->rawFd_.fd, player->rawFd_.offset, player->rawFd_.length);
319 if (ret != MSERR_OK) {
320 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetSource rawFd");
321 return undefinedResult;
322 }
323
324 ret = player->nativePlayer_->PrepareAsync();
325 if (ret != MSERR_OK) {
326 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to PrepareAsync");
327 return undefinedResult;
328 }
329
330 MEDIA_LOGD("SetFdSrc success");
331 return undefinedResult;
332 }
333
GetFdSrc(napi_env env,napi_callback_info info)334 napi_value AudioPlayerNapi::GetFdSrc(napi_env env, napi_callback_info info)
335 {
336 napi_value undefinedResult = nullptr;
337 napi_get_undefined(env, &undefinedResult);
338 napi_value jsThis = nullptr;
339 napi_value jsResult = nullptr;
340 AudioPlayerNapi *player = nullptr;
341 size_t argCount = 0;
342
343 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
344 if (status != napi_ok || jsThis == nullptr) {
345 MEDIA_LOGE("Failed to retrieve details about the callback");
346 return undefinedResult;
347 }
348
349 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
350 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "get player napi error");
351
352 status = napi_create_object(env, &jsResult);
353 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "create jsResult object error");
354
355 CHECK_AND_RETURN_RET(CommonNapi::AddNumberPropInt32(env, jsResult, "fd", player->rawFd_.fd) == true, nullptr);
356 CHECK_AND_RETURN_RET(CommonNapi::AddNumberPropInt64(env, jsResult, "offset", player->rawFd_.offset) == true,
357 nullptr);
358 CHECK_AND_RETURN_RET(CommonNapi::AddNumberPropInt64(env, jsResult, "length", player->rawFd_.length) == true,
359 nullptr);
360
361 MEDIA_LOGD("GetFdSrc success");
362 return jsResult;
363 }
364
Play(napi_env env,napi_callback_info info)365 napi_value AudioPlayerNapi::Play(napi_env env, napi_callback_info info)
366 {
367 napi_value undefinedResult = nullptr;
368 napi_get_undefined(env, &undefinedResult);
369
370 size_t argCount = 0;
371 napi_value jsThis = nullptr;
372 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
373 if (status != napi_ok || jsThis == nullptr) {
374 MEDIA_LOGE("Failed to retrieve details about the callback");
375 return undefinedResult;
376 }
377
378 AudioPlayerNapi *player = nullptr;
379 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
380 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "get player napi error");
381
382 if (player->nativePlayer_ == nullptr) {
383 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
384 return undefinedResult;
385 }
386 int32_t ret = player->nativePlayer_->Play();
387 if (ret != MSERR_OK) {
388 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to Play");
389 return undefinedResult;
390 }
391 MEDIA_LOGD("Play success");
392 return undefinedResult;
393 }
394
Pause(napi_env env,napi_callback_info info)395 napi_value AudioPlayerNapi::Pause(napi_env env, napi_callback_info info)
396 {
397 napi_value undefinedResult = nullptr;
398 napi_get_undefined(env, &undefinedResult);
399
400 size_t argCount = 0;
401 napi_value jsThis = nullptr;
402 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
403 if (status != napi_ok || jsThis == nullptr) {
404 MEDIA_LOGE("Failed to retrieve details about the callback");
405 return undefinedResult;
406 }
407
408 AudioPlayerNapi *player = nullptr;
409 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
410 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "get player napi error");
411
412 if (player->nativePlayer_ == nullptr) {
413 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
414 return undefinedResult;
415 }
416 int32_t ret = player->nativePlayer_->Pause();
417 if (ret != MSERR_OK) {
418 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to Pause");
419 return undefinedResult;
420 }
421 MEDIA_LOGD("Pause success");
422 return undefinedResult;
423 }
424
Stop(napi_env env,napi_callback_info info)425 napi_value AudioPlayerNapi::Stop(napi_env env, napi_callback_info info)
426 {
427 napi_value undefinedResult = nullptr;
428 napi_get_undefined(env, &undefinedResult);
429
430 size_t argCount = 0;
431 napi_value jsThis = nullptr;
432 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
433 if (status != napi_ok || jsThis == nullptr) {
434 MEDIA_LOGE("Failed to retrieve details about the callback");
435 return undefinedResult;
436 }
437
438 AudioPlayerNapi *player = nullptr;
439 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
440 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "get player napi error");
441
442 if (player->nativePlayer_ == nullptr) {
443 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
444 return undefinedResult;
445 }
446 int32_t ret = player->nativePlayer_->Stop();
447 if (ret != MSERR_OK) {
448 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to Stop");
449 return undefinedResult;
450 }
451 MEDIA_LOGD("Stop success");
452 return undefinedResult;
453 }
454
Reset(napi_env env,napi_callback_info info)455 napi_value AudioPlayerNapi::Reset(napi_env env, napi_callback_info info)
456 {
457 MEDIA_LOGD("AudioPlayerNapi Reset");
458 napi_value undefinedResult = nullptr;
459 napi_get_undefined(env, &undefinedResult);
460
461 size_t argCount = 0;
462 napi_value jsThis = nullptr;
463 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
464 if (status != napi_ok || jsThis == nullptr) {
465 MEDIA_LOGE("Failed to retrieve details about the callback");
466 return undefinedResult;
467 }
468
469 AudioPlayerNapi *player = nullptr;
470 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
471 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "get player napi error");
472
473 if (player->nativePlayer_ == nullptr) {
474 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
475 return undefinedResult;
476 }
477
478 int32_t ret = player->nativePlayer_->Reset();
479 if (ret != MSERR_OK) {
480 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to Reset");
481 return undefinedResult;
482 }
483 MEDIA_LOGD("Reset success");
484 return undefinedResult;
485 }
486
Release(napi_env env,napi_callback_info info)487 napi_value AudioPlayerNapi::Release(napi_env env, napi_callback_info info)
488 {
489 napi_value undefinedResult = nullptr;
490 napi_get_undefined(env, &undefinedResult);
491
492 size_t argCount = 0;
493 napi_value jsThis = nullptr;
494 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
495 if (status != napi_ok || jsThis == nullptr) {
496 MEDIA_LOGE("Failed to retrieve details about the callback");
497 return undefinedResult;
498 }
499
500 AudioPlayerNapi *player = nullptr;
501 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
502 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "get player napi error");
503
504 if (player->nativePlayer_ == nullptr) {
505 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
506 return undefinedResult;
507 }
508
509 (void)player->nativePlayer_->Release();
510 player->CancelCallback();
511 player->callbackNapi_ = nullptr;
512 player->nativePlayer_ = nullptr;
513 player->uri_.clear();
514 MEDIA_LOGD("Release success");
515 return undefinedResult;
516 }
517
Seek(napi_env env,napi_callback_info info)518 napi_value AudioPlayerNapi::Seek(napi_env env, napi_callback_info info)
519 {
520 napi_value undefinedResult = nullptr;
521 napi_get_undefined(env, &undefinedResult);
522
523 size_t argCount = 1;
524 napi_value args[1] = { nullptr };
525 napi_value jsThis = nullptr;
526
527 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
528 if (status != napi_ok || jsThis == nullptr || args[0] == nullptr) {
529 MEDIA_LOGE("Failed to retrieve details about the callback");
530 return undefinedResult;
531 }
532
533 AudioPlayerNapi *player = nullptr;
534 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
535 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
536 if (player->nativePlayer_ == nullptr) {
537 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
538 return undefinedResult;
539 }
540
541 napi_valuetype valueType = napi_undefined;
542 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
543 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
544 return undefinedResult;
545 }
546
547 int32_t position = -1;
548 status = napi_get_value_int32(env, args[0], &position);
549 if (status != napi_ok || position < 0) {
550 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
551 return undefinedResult;
552 }
553
554 int32_t ret = player->nativePlayer_->Seek(position, SEEK_PREVIOUS_SYNC);
555 if (ret != MSERR_OK) {
556 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to Seek");
557 return undefinedResult;
558 }
559
560 MEDIA_LOGD("Seek success");
561 return undefinedResult;
562 }
563
SetVolume(napi_env env,napi_callback_info info)564 napi_value AudioPlayerNapi::SetVolume(napi_env env, napi_callback_info info)
565 {
566 napi_value undefinedResult = nullptr;
567 napi_get_undefined(env, &undefinedResult);
568
569 size_t argCount = 1;
570 napi_value args[1] = { nullptr };
571 napi_value jsThis = nullptr;
572
573 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
574 if (status != napi_ok || jsThis == nullptr || args[0] == nullptr) {
575 MEDIA_LOGE("Failed to retrieve details about the callback");
576 return undefinedResult;
577 }
578
579 AudioPlayerNapi *player = nullptr;
580 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
581 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
582
583 if (player->nativePlayer_ == nullptr) {
584 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
585 return undefinedResult;
586 }
587
588 napi_valuetype valueType = napi_undefined;
589 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
590 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
591 return undefinedResult;
592 }
593
594 double volumeLevel;
595 status = napi_get_value_double(env, args[0], &volumeLevel);
596 if (status != napi_ok || volumeLevel < 0.0f || volumeLevel > 1.0f) {
597 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
598 return undefinedResult;
599 }
600
601 int32_t ret = player->nativePlayer_->SetVolume(static_cast<float>(volumeLevel), static_cast<float>(volumeLevel));
602 if (ret != MSERR_OK) {
603 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetVolume");
604 return undefinedResult;
605 }
606 MEDIA_LOGD("SetVolume success");
607 return undefinedResult;
608 }
609
On(napi_env env,napi_callback_info info)610 napi_value AudioPlayerNapi::On(napi_env env, napi_callback_info info)
611 {
612 napi_value undefinedResult = nullptr;
613 napi_get_undefined(env, &undefinedResult);
614
615 static constexpr size_t minArgCount = 2;
616 size_t argCount = minArgCount;
617 napi_value args[minArgCount] = { nullptr, nullptr };
618 napi_value jsThis = nullptr;
619 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
620 if (status != napi_ok || jsThis == nullptr || args[0] == nullptr || args[1] == nullptr) {
621 MEDIA_LOGE("Failed to retrieve details about the callback");
622 return undefinedResult;
623 }
624
625 AudioPlayerNapi *player = nullptr;
626 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
627 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
628
629 napi_valuetype valueType0 = napi_undefined;
630 napi_valuetype valueType1 = napi_undefined;
631 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string ||
632 napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
633 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
634 return undefinedResult;
635 }
636
637 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
638 MEDIA_LOGD("callbackName: %{public}s", callbackName.c_str());
639
640 napi_ref ref = nullptr;
641 status = napi_create_reference(env, args[1], 1, &ref);
642 CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, undefinedResult, "failed to create reference!");
643
644 std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
645 player->SetCallbackReference(callbackName, autoRef);
646 return undefinedResult;
647 }
648
SetLoop(napi_env env,napi_callback_info info)649 napi_value AudioPlayerNapi::SetLoop(napi_env env, napi_callback_info info)
650 {
651 size_t argCount = 1;
652 napi_value args[1] = { nullptr };
653 napi_value jsThis = nullptr;
654 napi_value undefinedResult = nullptr;
655 napi_get_undefined(env, &undefinedResult);
656
657 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
658 if (status != napi_ok || jsThis == nullptr || args[0] == nullptr) {
659 MEDIA_LOGE("Failed to retrieve details about the callback");
660 return undefinedResult;
661 }
662
663 AudioPlayerNapi *player = nullptr;
664 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
665 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
666
667 if (player->nativePlayer_ == nullptr) {
668 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
669 return undefinedResult;
670 }
671
672 napi_valuetype valueType = napi_undefined;
673 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_boolean) {
674 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
675 return undefinedResult;
676 }
677
678 bool loopFlag = false;
679 status = napi_get_value_bool(env, args[0], &loopFlag);
680 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_get_value_bool error");
681
682 int32_t ret = player->nativePlayer_->SetLooping(loopFlag);
683 if (ret != MSERR_OK) {
684 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetLooping");
685 return undefinedResult;
686 }
687
688 MEDIA_LOGD("SetLoop success");
689 return undefinedResult;
690 }
691
692
GetLoop(napi_env env,napi_callback_info info)693 napi_value AudioPlayerNapi::GetLoop(napi_env env, napi_callback_info info)
694 {
695 napi_value jsThis = nullptr;
696 napi_value jsResult = nullptr;
697 napi_value undefinedResult = nullptr;
698 napi_get_undefined(env, &undefinedResult);
699
700 size_t argCount = 0;
701 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
702 if (status != napi_ok || jsThis == nullptr) {
703 MEDIA_LOGE("Failed to retrieve details about the callback");
704 return undefinedResult;
705 }
706
707 AudioPlayerNapi *player = nullptr;
708 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
709 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
710
711 if (player->nativePlayer_ == nullptr) {
712 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
713 return undefinedResult;
714 }
715 bool loopFlag = player->nativePlayer_->IsLooping();
716
717 status = napi_get_boolean(env, loopFlag, &jsResult);
718 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_get_boolean error");
719
720 MEDIA_LOGD("GetSrc success loop Status: %{public}d", loopFlag);
721 return jsResult;
722 }
723
GetCurrentTime(napi_env env,napi_callback_info info)724 napi_value AudioPlayerNapi::GetCurrentTime(napi_env env, napi_callback_info info)
725 {
726 napi_value jsThis = nullptr;
727 napi_value undefinedResult = nullptr;
728 napi_get_undefined(env, &undefinedResult);
729
730 size_t argCount = 0;
731 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
732 if (status != napi_ok || jsThis == nullptr) {
733 MEDIA_LOGE("Failed to retrieve details about the callback");
734 return undefinedResult;
735 }
736
737 AudioPlayerNapi *player = nullptr;
738 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
739 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
740
741 if (player->nativePlayer_ == nullptr) {
742 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
743 return undefinedResult;
744 }
745 int32_t currentTime = -1;
746 (void)player->nativePlayer_->GetCurrentTime(currentTime);
747
748 napi_value jsResult = nullptr;
749 status = napi_create_int32(env, currentTime, &jsResult);
750 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
751
752 MEDIA_LOGD("GetCurrenTime success, Current time: %{public}d", currentTime);
753 return jsResult;
754 }
755
GetDuration(napi_env env,napi_callback_info info)756 napi_value AudioPlayerNapi::GetDuration(napi_env env, napi_callback_info info)
757 {
758 napi_value jsThis = nullptr;
759 napi_value jsResult = nullptr;
760 napi_value undefinedResult = nullptr;
761 napi_get_undefined(env, &undefinedResult);
762
763 size_t argCount = 0;
764 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
765 if (status != napi_ok || jsThis == nullptr) {
766 MEDIA_LOGE("Failed to retrieve details about the callback");
767 return undefinedResult;
768 }
769
770 AudioPlayerNapi *player = nullptr;
771 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
772 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
773
774 if (player->nativePlayer_ == nullptr) {
775 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
776 return undefinedResult;
777 }
778 int32_t duration = -1;
779 (void)player->nativePlayer_->GetDuration(duration);
780
781 status = napi_create_int32(env, duration, &jsResult);
782 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int64 error");
783
784 MEDIA_LOGD("GetDuration success, Current time: %{public}d", duration);
785 return jsResult;
786 }
787
GetJSState(PlayerStates currentState)788 static std::string GetJSState(PlayerStates currentState)
789 {
790 std::string result;
791
792 MEDIA_LOGD("GetJSState()! is called!, %{public}d", currentState);
793 switch (currentState) {
794 case PLAYER_IDLE:
795 case PLAYER_INITIALIZED:
796 case PLAYER_PREPARING:
797 case PLAYER_PREPARED:
798 result = STATE_IDLE;
799 break;
800 case PLAYER_STARTED:
801 result = STATE_PLAYING;
802 break;
803 case PLAYER_PAUSED:
804 result = STATE_PAUSED;
805 break;
806 case PLAYER_STOPPED:
807 case PLAYER_PLAYBACK_COMPLETE:
808 result = STATE_STOPPED;
809 break;
810 default:
811 // Considering default state as stopped
812 MEDIA_LOGE("Error state! %{public}d", currentState);
813 result = STATE_ERROR;
814 break;
815 }
816 return result;
817 }
818
GetState(napi_env env,napi_callback_info info)819 napi_value AudioPlayerNapi::GetState(napi_env env, napi_callback_info info)
820 {
821 napi_value jsThis = nullptr;
822 napi_value jsResult = nullptr;
823 napi_value undefinedResult = nullptr;
824 std::string curState;
825 napi_get_undefined(env, &undefinedResult);
826
827 size_t argCount = 0;
828 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
829 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "Failed to retrieve details about the callback");
830
831 AudioPlayerNapi *player = nullptr;
832 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
833 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "Failed to retrieve instance");
834
835 if (player->callbackNapi_ == nullptr) {
836 return undefinedResult;
837 } else {
838 std::shared_ptr<PlayerCallbackNapi> cb = std::static_pointer_cast<PlayerCallbackNapi>(player->callbackNapi_);
839 curState = GetJSState(cb->GetCurrentState());
840 MEDIA_LOGD("GetState success, State: %{public}s", curState.c_str());
841 }
842 status = napi_create_string_utf8(env, curState.c_str(), NAPI_AUTO_LENGTH, &jsResult);
843 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_string_utf8 error");
844 return jsResult;
845 }
846
ErrorCallback(MediaServiceExtErrCode errCode,std::string errMsg)847 void AudioPlayerNapi::ErrorCallback(MediaServiceExtErrCode errCode, std::string errMsg)
848 {
849 if (callbackNapi_ != nullptr) {
850 std::shared_ptr<PlayerCallbackNapi> napiCb = std::static_pointer_cast<PlayerCallbackNapi>(callbackNapi_);
851 napiCb->SendErrorCallback(errCode, errMsg);
852 }
853 }
854
AsyncGetTrackDescription(napi_env env,void * data)855 void AudioPlayerNapi::AsyncGetTrackDescription(napi_env env, void *data)
856 {
857 auto asyncContext = reinterpret_cast<AudioPlayerAsyncContext *>(data);
858 CHECK_AND_RETURN_LOG(asyncContext != nullptr, "AudioPlayerAsyncContext is nullptr!");
859
860 if (asyncContext->jsPlayer == nullptr) {
861 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "jsPlayer is destroyed(null), please check js_runtime");
862 return;
863 }
864
865 if (asyncContext->jsPlayer->nativePlayer_ == nullptr) {
866 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "nativePlayer is released(null), please create player again");
867 return;
868 }
869
870 auto player = asyncContext->jsPlayer->nativePlayer_;
871 std::vector<Format> &audioInfo = asyncContext->jsPlayer->audioTrackInfoVec_;
872 audioInfo.clear();
873 int32_t ret = player->GetAudioTrackInfo(audioInfo);
874 if (ret != MSERR_OK) {
875 asyncContext->SignError(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)),
876 "failed to GetAudioTrackInfo");
877 return;
878 }
879
880 if (audioInfo.empty()) {
881 asyncContext->SignError(MSERR_EXT_OPERATE_NOT_PERMIT, "audio track info is empty");
882 return;
883 }
884
885 asyncContext->JsResult = std::make_unique<MediaJsResultArray>(audioInfo);
886 MEDIA_LOGD("AsyncGetTrackDescription Out");
887 }
888
GetTrackDescription(napi_env env,napi_callback_info info)889 napi_value AudioPlayerNapi::GetTrackDescription(napi_env env, napi_callback_info info)
890 {
891 napi_value result = nullptr;
892 napi_get_undefined(env, &result);
893
894 MEDIA_LOGD("GetTrackDescription In");
895 std::unique_ptr<AudioPlayerAsyncContext> asyncContext = std::make_unique<AudioPlayerAsyncContext>(env);
896
897 // get args
898 napi_value jsThis = nullptr;
899 napi_value args[1] = { nullptr };
900 size_t argCount = 1;
901 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
902 if (status != napi_ok || jsThis == nullptr) {
903 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
904 }
905
906 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
907 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
908 // get jsPlayer
909 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
910 // async work
911 napi_value resource = nullptr;
912 napi_create_string_utf8(env, "GetTrackDescription", NAPI_AUTO_LENGTH, &resource);
913 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, AudioPlayerNapi::AsyncGetTrackDescription,
914 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncContext.get()), &asyncContext->work));
915 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
916 asyncContext.release();
917 return result;
918 }
919
SetAudioInterruptMode(napi_env env,napi_callback_info info)920 napi_value AudioPlayerNapi::SetAudioInterruptMode(napi_env env, napi_callback_info info)
921 {
922 size_t argCount = 1;
923 napi_value args[1] = { nullptr };
924 napi_value jsThis = nullptr;
925 napi_value undefinedResult = nullptr;
926 napi_get_undefined(env, &undefinedResult);
927
928 MEDIA_LOGD("SetAudioInterruptMode In");
929 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
930 if (status != napi_ok || jsThis == nullptr || args[0] == nullptr) {
931 MEDIA_LOGE("Failed to retrieve details about the callback");
932 return undefinedResult;
933 }
934
935 AudioPlayerNapi *player = nullptr;
936 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
937 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
938
939 if (player->nativePlayer_ == nullptr) {
940 player->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
941 return undefinedResult;
942 }
943
944 napi_valuetype valueType = napi_undefined;
945 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
946 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
947 return undefinedResult;
948 }
949
950 int32_t interruptMode = 0;
951 status = napi_get_value_int32(env, args[0], &interruptMode);
952 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_get_value_int32 error");
953
954 if (interruptMode < AudioStandard::InterruptMode::SHARE_MODE ||
955 interruptMode > AudioStandard::InterruptMode::INDEPENDENT_MODE) {
956 player->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
957 return undefinedResult;
958 }
959
960 player->interruptMode_ = AudioStandard::InterruptMode(interruptMode);
961 Format format;
962 (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_MODE, interruptMode);
963 int32_t ret = player->nativePlayer_->SetParameter(format);
964 if (ret != MSERR_OK) {
965 player->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetParameter");
966 return undefinedResult;
967 }
968
969 MEDIA_LOGD("SetAudioInterruptMode success");
970 return undefinedResult;
971 }
972
GetAudioInterruptMode(napi_env env,napi_callback_info info)973 napi_value AudioPlayerNapi::GetAudioInterruptMode(napi_env env, napi_callback_info info)
974 {
975 napi_value jsThis = nullptr;
976 napi_value jsResult = nullptr;
977 napi_value undefinedResult = nullptr;
978 napi_get_undefined(env, &undefinedResult);
979
980 size_t argCount = 0;
981 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
982 if (status != napi_ok || jsThis == nullptr) {
983 MEDIA_LOGE("Failed to retrieve details about the callback");
984 return undefinedResult;
985 }
986
987 AudioPlayerNapi *player = nullptr;
988 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
989 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
990
991 status = napi_create_object(env, &jsResult);
992 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "create jsresult object error");
993
994 CHECK_AND_RETURN_RET(CommonNapi::AddNumberPropInt32(env, jsResult, "InterruptMode",
995 player->interruptMode_) == true, nullptr);
996 MEDIA_LOGD("GetAudioInterruptMode success");
997 return jsResult;
998 }
999
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)1000 void AudioPlayerNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
1001 {
1002 refMap_[callbackName] = ref;
1003 if (callbackNapi_ != nullptr) {
1004 std::shared_ptr<PlayerCallbackNapi> napiCb = std::static_pointer_cast<PlayerCallbackNapi>(callbackNapi_);
1005 napiCb->SaveCallbackReference(callbackName, ref);
1006 }
1007 }
1008
CancelCallback()1009 void AudioPlayerNapi::CancelCallback()
1010 {
1011 if (callbackNapi_ != nullptr) {
1012 std::shared_ptr<PlayerCallbackNapi> napiCb = std::static_pointer_cast<PlayerCallbackNapi>(callbackNapi_);
1013 napiCb->ClearCallbackReference();
1014 }
1015 }
1016 } // namespace Media
1017 } // namespace OHOS
1018