1 /*
2 * Copyright (c) 2023 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 "ringtone_player_napi.h"
17
18 #include "audio_renderer_info_napi.h"
19 #include "avplayer_napi.h"
20 #include "system_sound_log.h"
21
22 using namespace std;
23
24 namespace {
25 /* Constants for array index */
26 const int32_t PARAM0 = 0;
27 const int32_t PARAM1 = 1;
28
29 /* Constants for array size */
30 const int32_t ARGS_ONE = 1;
31 const int32_t ARGS_TWO = 2;
32
33 const std::string AUDIO_INTERRUPT_CALLBACK_NAME = "audioInterrupt";
34
35 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "RingtonePlayerNapi"};
36
37 const int SUCCESS = 0;
38 }
39
40 namespace OHOS {
41 namespace Media {
42 static const std::map<RingtoneState, std::string> STATEMAP = {
43 {STATE_INVALID, AVPlayerState::STATE_ERROR},
44 {STATE_NEW, AVPlayerState::STATE_INITIALIZED},
45 {STATE_PREPARED, AVPlayerState::STATE_PREPARED},
46 {STATE_RUNNING, AVPlayerState::STATE_PLAYING},
47 {STATE_STOPPED, AVPlayerState::STATE_STOPPED},
48 {STATE_RELEASED, AVPlayerState::STATE_RELEASED},
49 {STATE_PAUSED, AVPlayerState::STATE_PAUSED},
50 };
51
52 thread_local napi_ref RingtonePlayerNapi::sConstructor_ = nullptr;
53 shared_ptr<RingtonePlayer> RingtonePlayerNapi::sRingtonePlayer_ = nullptr;
54
RingtonePlayerNapi()55 RingtonePlayerNapi::RingtonePlayerNapi() : env_(nullptr) {}
56
57 RingtonePlayerNapi::~RingtonePlayerNapi() = default;
58
ThrowErrorAndReturn(napi_env env,int32_t errCode,const std::string & errMessage)59 static napi_value ThrowErrorAndReturn(napi_env env, int32_t errCode, const std::string &errMessage)
60 {
61 RingtoneCommonNapi::ThrowError(env, errCode, errMessage);
62 return nullptr;
63 }
64
Init(napi_env env,napi_value exports)65 napi_value RingtonePlayerNapi::Init(napi_env env, napi_value exports)
66 {
67 napi_status status;
68 napi_value ctorObj;
69 int32_t refCount = 1;
70
71 napi_property_descriptor ringtone_player_prop[] = {
72 DECLARE_NAPI_FUNCTION("getTitle", GetTitle),
73 DECLARE_NAPI_FUNCTION("getAudioRendererInfo", GetAudioRendererInfo),
74 DECLARE_NAPI_FUNCTION("configure", Configure),
75 DECLARE_NAPI_FUNCTION("start", Start),
76 DECLARE_NAPI_FUNCTION("stop", Stop),
77 DECLARE_NAPI_FUNCTION("release", Release),
78 DECLARE_NAPI_FUNCTION("on", On),
79 DECLARE_NAPI_FUNCTION("off", Off),
80 DECLARE_NAPI_GETTER("state", GetAudioState)
81 };
82
83 status = napi_define_class(env, RINGTONE_PLAYER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
84 RingtonePlayerNapiConstructor, nullptr, sizeof(ringtone_player_prop) / sizeof(ringtone_player_prop[0]),
85 ringtone_player_prop, &ctorObj);
86 if (status == napi_ok) {
87 if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
88 status = napi_set_named_property(env, exports, RINGTONE_PLAYER_NAPI_CLASS_NAME.c_str(), ctorObj);
89 if (status == napi_ok) {
90 return exports;
91 }
92 }
93 }
94
95 return nullptr;
96 }
97
RingtonePlayerNapiConstructor(napi_env env,napi_callback_info info)98 napi_value RingtonePlayerNapi::RingtonePlayerNapiConstructor(napi_env env, napi_callback_info info)
99 {
100 napi_status status;
101 napi_value result = nullptr;
102 napi_value thisVar = nullptr;
103
104 napi_get_undefined(env, &result);
105 status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
106 if (status == napi_ok && thisVar != nullptr) {
107 std::unique_ptr<RingtonePlayerNapi> obj = std::make_unique<RingtonePlayerNapi>();
108 if (obj != nullptr) {
109 obj->env_ = env;
110 if (obj->sRingtonePlayer_ != nullptr) {
111 obj->ringtonePlayer_ = move(obj->sRingtonePlayer_);
112 } else {
113 MEDIA_LOGE("Failed to create sRingtonePlayer_ instance.");
114 return result;
115 }
116
117 if (obj->ringtonePlayer_ != nullptr && obj->callbackNapi_ == nullptr) {
118 obj->callbackNapi_ = std::make_shared<RingtonePlayerCallbackNapi>(env);
119 CHECK_AND_RETURN_RET_LOG(obj->callbackNapi_ != nullptr, result, "No memory");
120 int32_t ret = obj->ringtonePlayer_->SetRingtonePlayerInterruptCallback(obj->callbackNapi_);
121 MEDIA_LOGI("AudioRendererNapi::Construct SetRendererCallback %{public}s",
122 ret == 0 ? "succeess" : "failed");
123 }
124
125 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
126 RingtonePlayerNapi::RingtonePlayerNapiDestructor, nullptr, nullptr);
127 if (status == napi_ok) {
128 obj.release();
129 return thisVar;
130 } else {
131 MEDIA_LOGE("Failed to wrap the native rngplyrmngr object with JS.");
132 }
133 }
134 }
135
136 return result;
137 }
138
RingtonePlayerNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)139 void RingtonePlayerNapi::RingtonePlayerNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
140 {
141 RingtonePlayerNapi *ringtonePlayerHelper = reinterpret_cast<RingtonePlayerNapi*>(nativeObject);
142 if (ringtonePlayerHelper != nullptr) {
143 ringtonePlayerHelper->~RingtonePlayerNapi();
144 }
145 }
146
GetRingtonePlayerInstance(napi_env env,shared_ptr<RingtonePlayer> & ringtonePlayer)147 napi_value RingtonePlayerNapi::GetRingtonePlayerInstance(napi_env env, shared_ptr<RingtonePlayer> &ringtonePlayer)
148 {
149 napi_status status;
150 napi_value result = nullptr;
151 napi_value ctor;
152
153 status = napi_get_reference_value(env, sConstructor_, &ctor);
154 if (status == napi_ok) {
155 sRingtonePlayer_ = ringtonePlayer;
156 status = napi_new_instance(env, ctor, 0, nullptr, &result);
157 if (status == napi_ok) {
158 return result;
159 } else {
160 MEDIA_LOGE("GetRingtonePlayerInstance: New instance could not be obtained.");
161 }
162 }
163
164 napi_get_undefined(env, &result);
165 return result;
166 }
167
CommonAsyncCallbackComplete(napi_env env,napi_status status,void * data)168 void RingtonePlayerNapi::CommonAsyncCallbackComplete(napi_env env, napi_status status, void* data)
169 {
170 auto context = static_cast<RingtonePlayerAsyncContext *>(data);
171 napi_value callback = nullptr;
172 napi_value retVal = nullptr;
173 napi_value result[2] = {};
174
175 napi_get_undefined(env, &result[PARAM1]);
176 if (!context->status) {
177 napi_get_undefined(env, &result[PARAM0]);
178 } else {
179 napi_value message = nullptr;
180 napi_create_string_utf8(env, "Error: Operation is not supported or failed", NAPI_AUTO_LENGTH, &message);
181 napi_create_error(env, nullptr, message, &result[PARAM0]);
182 }
183
184 if (context->deferred) {
185 if (!context->status) {
186 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
187 } else {
188 napi_reject_deferred(env, context->deferred, result[PARAM0]);
189 }
190 } else {
191 napi_get_reference_value(env, context->callbackRef, &callback);
192 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
193 napi_delete_reference(env, context->callbackRef);
194 }
195 napi_delete_async_work(env, context->work);
196
197 delete context;
198 context = nullptr;
199 }
200
GetTitleAsyncCallbackComplete(napi_env env,napi_status status,void * data)201 void RingtonePlayerNapi::GetTitleAsyncCallbackComplete(napi_env env, napi_status status, void *data)
202 {
203 auto context = static_cast<RingtonePlayerAsyncContext *>(data);
204 napi_value getTitleCallback = nullptr;
205 napi_value retVal = nullptr;
206 napi_value result[2] = {};
207
208 if (!context->status) {
209 napi_get_undefined(env, &result[PARAM0]);
210 napi_create_string_utf8(env, context->title.c_str(), NAPI_AUTO_LENGTH, &result[PARAM1]);
211 } else {
212 napi_value message = nullptr;
213 napi_create_string_utf8(env, "GetTitle Error: Operation is not supported or failed",
214 NAPI_AUTO_LENGTH, &message);
215 napi_create_error(env, nullptr, message, &result[PARAM0]);
216 napi_get_undefined(env, &result[PARAM1]);
217 }
218
219 if (context->deferred) {
220 if (!context->status) {
221 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
222 } else {
223 napi_reject_deferred(env, context->deferred, result[PARAM0]);
224 }
225 } else {
226 napi_get_reference_value(env, context->callbackRef, &getTitleCallback);
227 napi_call_function(env, nullptr, getTitleCallback, ARGS_TWO, result, &retVal);
228 napi_delete_reference(env, context->callbackRef);
229 }
230 napi_delete_async_work(env, context->work);
231
232 delete context;
233 context = nullptr;
234 }
235
GetTitle(napi_env env,napi_callback_info info)236 napi_value RingtonePlayerNapi::GetTitle(napi_env env, napi_callback_info info)
237 {
238 napi_status status;
239 napi_value result = nullptr;
240 napi_value resource = nullptr;
241 size_t argc = ARGS_ONE;
242 napi_value argv[ARGS_ONE] = {0};
243 napi_value thisVar = nullptr;
244 const int32_t refCount = 1;
245
246 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
247 napi_get_undefined(env, &result);
248 if (status != napi_ok || thisVar == nullptr) {
249 MEDIA_LOGE("GetTitle: Failed to retrieve details about the callback");
250 return result;
251 }
252
253 NAPI_ASSERT(env, argc <= ARGS_ONE, "GetTitle: requires 1 parameter maximum");
254 std::unique_ptr<RingtonePlayerAsyncContext> asyncContext = std::make_unique<RingtonePlayerAsyncContext>();
255 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
256 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
257 if (argc == ARGS_ONE) {
258 napi_valuetype valueType = napi_undefined;
259 napi_typeof(env, argv[PARAM0], &valueType);
260 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
261 "GetTitle: the param type is not napi_function");
262 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
263 } else {
264 napi_create_promise(env, &asyncContext->deferred, &result);
265 }
266
267 napi_create_string_utf8(env, "GetTitle", NAPI_AUTO_LENGTH, &resource);
268 status = napi_create_async_work(env, nullptr, resource,
269 [](napi_env env, void *data) {
270 RingtonePlayerAsyncContext *context = static_cast<RingtonePlayerAsyncContext *>(data);
271 context->title = context->objectInfo->ringtonePlayer_->GetTitle();
272 context->status = SUCCESS;
273 },
274 GetTitleAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
275 if (status != napi_ok) {
276 MEDIA_LOGE("GetTitle: Failed to get create async work");
277 napi_get_undefined(env, &result);
278 } else {
279 napi_queue_async_work(env, asyncContext->work);
280 asyncContext.release();
281 }
282 }
283
284 return result;
285 }
286
GetAudioRendererInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)287 void RingtonePlayerNapi::GetAudioRendererInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
288 {
289 auto context = static_cast<RingtonePlayerAsyncContext *>(data);
290 napi_value getRendererInfoCallback = nullptr;
291 napi_value retVal = nullptr;
292 napi_value valueParam = nullptr;
293 napi_value result[2] = {};
294
295 if (!context->status) {
296 unique_ptr<AudioStandard::AudioRendererInfo> audioRendererInfo =
297 make_unique<AudioStandard::AudioRendererInfo>();
298 audioRendererInfo->contentType = context->contentType;
299 audioRendererInfo->streamUsage = context->streamUsage;
300 audioRendererInfo->rendererFlags = context->rendererFlags;
301
302 valueParam = AudioRendererInfoNapi::CreateAudioRendererInfoWrapper(env, audioRendererInfo);
303 napi_get_undefined(env, &result[PARAM0]);
304 result[PARAM1] = valueParam;
305 } else {
306 napi_value message = nullptr;
307 napi_create_string_utf8(env, "GetRendererInfo Error: Operation is not supported or failed",
308 NAPI_AUTO_LENGTH, &message);
309 napi_create_error(env, nullptr, message, &result[PARAM0]);
310 napi_get_undefined(env, &result[PARAM1]);
311 }
312
313 if (context->deferred) {
314 if (!context->status) {
315 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
316 } else {
317 napi_reject_deferred(env, context->deferred, result[PARAM0]);
318 }
319 } else {
320 napi_get_reference_value(env, context->callbackRef, &getRendererInfoCallback);
321 napi_call_function(env, nullptr, getRendererInfoCallback, ARGS_TWO, result, &retVal);
322 napi_delete_reference(env, context->callbackRef);
323 }
324 napi_delete_async_work(env, context->work);
325
326 delete context;
327 context = nullptr;
328 }
329
GetAudioRendererInfo(napi_env env,napi_callback_info info)330 napi_value RingtonePlayerNapi::GetAudioRendererInfo(napi_env env, napi_callback_info info)
331 {
332 napi_status status;
333 napi_value result = nullptr;
334 napi_value resource = nullptr;
335 size_t argc = ARGS_ONE;
336 napi_value argv[ARGS_ONE] = {0};
337 napi_value thisVar = nullptr;
338 const int32_t refCount = 1;
339
340 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
341 napi_get_undefined(env, &result);
342 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
343 "GetAudioRendererInfo: Failed to retrieve details about the callback");
344
345 NAPI_ASSERT(env, argc <= ARGS_ONE, "GetAudioRendererInfo: requires 1 parameter maximum");
346 std::unique_ptr<RingtonePlayerAsyncContext> asyncContext = std::make_unique<RingtonePlayerAsyncContext>();
347 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
348 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
349 if (argc == ARGS_ONE) {
350 napi_valuetype valueType = napi_undefined;
351 napi_typeof(env, argv[PARAM0], &valueType);
352 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
353 "GetAudioRendererInfo: the param type is not napi_function");
354 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
355 } else {
356 napi_create_promise(env, &asyncContext->deferred, &result);
357 }
358
359 napi_create_string_utf8(env, "GetAudioRendererInfo", NAPI_AUTO_LENGTH, &resource);
360 status = napi_create_async_work(env, nullptr, resource, AsyncGetAudioRendererInfo,
361 GetAudioRendererInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
362 if (status != napi_ok) {
363 MEDIA_LOGE("GetAudioRendererInfo: Failed to get create async work");
364 napi_get_undefined(env, &result);
365 } else {
366 napi_queue_async_work(env, asyncContext->work);
367 asyncContext.release();
368 }
369 }
370
371 return result;
372 }
373
AsyncGetAudioRendererInfo(napi_env env,void * data)374 void RingtonePlayerNapi::AsyncGetAudioRendererInfo(napi_env env, void *data)
375 {
376 RingtonePlayerAsyncContext *context = static_cast<RingtonePlayerAsyncContext *>(data);
377 AudioStandard::AudioRendererInfo rendererInfo;
378 context->status = context->objectInfo->ringtonePlayer_->GetAudioRendererInfo(rendererInfo);
379 if (context->status == SUCCESS) {
380 context->contentType = rendererInfo.contentType;
381 context->streamUsage = rendererInfo.streamUsage;
382 context->rendererFlags = rendererInfo.rendererFlags;
383 }
384 }
385
Configure(napi_env env,napi_callback_info info)386 napi_value RingtonePlayerNapi::Configure(napi_env env, napi_callback_info info)
387 {
388 napi_value result = nullptr;
389 napi_value resource = nullptr;
390 napi_value property = nullptr;
391 size_t argc = ARGS_TWO;
392 napi_value argv[ARGS_TWO] = {0};
393 napi_value thisVar = nullptr;
394 const int32_t refCount = 1;
395 double volume = 1.0;
396
397 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
398 napi_get_undefined(env, &result);
399 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result, "Configure: napi_get_cb_info failed");
400
401 NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameters maximum");
402 std::unique_ptr<RingtonePlayerAsyncContext> asyncContext = std::make_unique<RingtonePlayerAsyncContext>();
403 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
404 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
405 napi_valuetype valueType = napi_undefined;
406 napi_typeof(env, argv[PARAM0], &valueType);
407 if (valueType == napi_object) {
408 if ((napi_get_named_property(env, argv[PARAM0], "volume", &property) != napi_ok)
409 || napi_get_value_double(env, property, &volume) != napi_ok) {
410 NAPI_ASSERT(env, false, "missing volume properties");
411 }
412 asyncContext->volume = (float)volume;
413
414 if ((napi_get_named_property(env, argv[PARAM0], "loop", &property) != napi_ok)
415 || napi_get_value_bool(env, property, &asyncContext->loop) != napi_ok) {
416 NAPI_ASSERT(env, false, "missing loop properties");
417 }
418 }
419
420 if (argc == ARGS_TWO) {
421 napi_typeof(env, argv[PARAM1], &valueType);
422 if (valueType == napi_function) {
423 napi_create_reference(env, argv[PARAM1], refCount, &asyncContext->callbackRef);
424 }
425 } else {
426 napi_create_promise(env, &asyncContext->deferred, &result);
427 }
428
429 napi_create_string_utf8(env, "Configure", NAPI_AUTO_LENGTH, &resource);
430 status = napi_create_async_work(env, nullptr, resource, AsyncConfigure,
431 CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
432 if (status != napi_ok) {
433 MEDIA_LOGE("Configure: Failed to create async work");
434 napi_get_undefined(env, &result);
435 } else {
436 napi_queue_async_work(env, asyncContext->work);
437 asyncContext.release();
438 }
439 }
440
441 return result;
442 }
443
AsyncConfigure(napi_env env,void * data)444 void RingtonePlayerNapi::AsyncConfigure(napi_env env, void *data)
445 {
446 RingtonePlayerAsyncContext* context = static_cast<RingtonePlayerAsyncContext*>(data);
447 context->status = context->objectInfo->ringtonePlayer_->Configure(context->volume, context->loop);
448 }
449
Start(napi_env env,napi_callback_info info)450 napi_value RingtonePlayerNapi::Start(napi_env env, napi_callback_info info)
451 {
452 napi_status status;
453 napi_value result = nullptr;
454 napi_value resource = nullptr;
455 size_t argc = ARGS_ONE;
456 napi_value argv[ARGS_ONE] = {0};
457 napi_value thisVar = nullptr;
458 const int32_t refCount = 1;
459
460 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
461 napi_get_undefined(env, &result);
462 if (status != napi_ok || thisVar == nullptr) {
463 MEDIA_LOGE("Start: Failed to retrieve details about the callback");
464 return result;
465 }
466
467 NAPI_ASSERT(env, argc <= ARGS_ONE, "Start: requires 1 parameter maximum");
468 std::unique_ptr<RingtonePlayerAsyncContext> asyncContext = std::make_unique<RingtonePlayerAsyncContext>();
469 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
470 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
471 if (argc == ARGS_ONE) {
472 napi_valuetype valueType = napi_undefined;
473 napi_typeof(env, argv[PARAM0], &valueType);
474 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
475 "Start: the param type is not napi_function");
476 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
477 } else {
478 napi_create_promise(env, &asyncContext->deferred, &result);
479 }
480
481 napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
482 status = napi_create_async_work(env, nullptr, resource,
483 [](napi_env env, void* data) {
484 RingtonePlayerAsyncContext* context = static_cast<RingtonePlayerAsyncContext*>(data);
485 context->status = context->objectInfo->ringtonePlayer_->Start();
486 },
487 CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
488 if (status != napi_ok) {
489 MEDIA_LOGE("Start: Failed to get create async work");
490 napi_get_undefined(env, &result);
491 } else {
492 napi_queue_async_work(env, asyncContext->work);
493 asyncContext.release();
494 }
495 }
496
497 return result;
498 }
499
Stop(napi_env env,napi_callback_info info)500 napi_value RingtonePlayerNapi::Stop(napi_env env, napi_callback_info info)
501 {
502 napi_status status;
503 napi_value result = nullptr;
504 napi_value resource = nullptr;
505 size_t argc = ARGS_ONE;
506 napi_value argv[ARGS_ONE] = {0};
507 napi_value thisVar = nullptr;
508 const int32_t refCount = 1;
509
510 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
511 napi_get_undefined(env, &result);
512 if (status != napi_ok || thisVar == nullptr) {
513 MEDIA_LOGE("Stop: Failed to retrieve details about the callback");
514 return result;
515 }
516
517 NAPI_ASSERT(env, argc <= ARGS_ONE, "Stop: requires 1 parameter maximum");
518 std::unique_ptr<RingtonePlayerAsyncContext> asyncContext = std::make_unique<RingtonePlayerAsyncContext>();
519 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
520 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
521 if (argc == ARGS_ONE) {
522 napi_valuetype valueType = napi_undefined;
523 napi_typeof(env, argv[PARAM0], &valueType);
524 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
525 "Stop: the param type is not napi_function");
526 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
527 } else {
528 napi_create_promise(env, &asyncContext->deferred, &result);
529 }
530
531 napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
532 status = napi_create_async_work(env, nullptr, resource,
533 [](napi_env env, void* data) {
534 RingtonePlayerAsyncContext* context = static_cast<RingtonePlayerAsyncContext*>(data);
535 context->status = context->objectInfo->ringtonePlayer_->Stop();
536 },
537 CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
538 if (status != napi_ok) {
539 MEDIA_LOGE("Stop: Failed to get create async work");
540 napi_get_undefined(env, &result);
541 } else {
542 napi_queue_async_work(env, asyncContext->work);
543 asyncContext.release();
544 }
545 }
546
547 return result;
548 }
549
Release(napi_env env,napi_callback_info info)550 napi_value RingtonePlayerNapi::Release(napi_env env, napi_callback_info info)
551 {
552 napi_status status;
553 napi_value result = nullptr;
554 napi_value resource = nullptr;
555 size_t argc = ARGS_ONE;
556 napi_value argv[ARGS_ONE] = {0};
557 napi_value thisVar = nullptr;
558 const int32_t refCount = 1;
559
560 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
561 napi_get_undefined(env, &result);
562 if (status != napi_ok || thisVar == nullptr) {
563 MEDIA_LOGE("Release: Failed to retrieve details about the callback");
564 return result;
565 }
566
567 NAPI_ASSERT(env, argc <= ARGS_ONE, "Release: requires 1 parameter maximum");
568 std::unique_ptr<RingtonePlayerAsyncContext> asyncContext = std::make_unique<RingtonePlayerAsyncContext>();
569 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
570 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
571 if (argc == ARGS_ONE) {
572 napi_valuetype valueType = napi_undefined;
573 napi_typeof(env, argv[PARAM0], &valueType);
574 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
575 "Release: the param type is not napi_function");
576 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
577 } else {
578 napi_create_promise(env, &asyncContext->deferred, &result);
579 }
580
581 napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
582 status = napi_create_async_work(env, nullptr, resource,
583 [](napi_env env, void* data) {
584 RingtonePlayerAsyncContext* context = static_cast<RingtonePlayerAsyncContext*>(data);
585 context->status = context->objectInfo->ringtonePlayer_->Release();
586 },
587 CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
588 if (status != napi_ok) {
589 MEDIA_LOGE("Release: Failed to get create async work");
590 napi_get_undefined(env, &result);
591 } else {
592 napi_queue_async_work(env, asyncContext->work);
593 asyncContext.release();
594 }
595 }
596
597 return result;
598 }
599
GetAudioState(napi_env env,napi_callback_info info)600 napi_value RingtonePlayerNapi::GetAudioState(napi_env env, napi_callback_info info)
601 {
602 napi_status status;
603 size_t argc = 0;
604 napi_value thisVar = nullptr;
605 napi_value result = nullptr;
606 napi_get_undefined(env, &result);
607
608 status = napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
609 if (status != napi_ok || thisVar == nullptr) {
610 MEDIA_LOGE("GetAudioState: fail to napi_get_cb_info");
611 return result;
612 }
613
614 std::string curState = AVPlayerState::STATE_ERROR;
615 std::unique_ptr<RingtonePlayerAsyncContext> asyncContext
616 = std::make_unique<RingtonePlayerAsyncContext>();
617 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
618 if (status == napi_ok && asyncContext->objectInfo && asyncContext->objectInfo->ringtonePlayer_ != nullptr) {
619 RingtoneState ringtoneState_ = asyncContext->objectInfo->ringtonePlayer_->GetRingtoneState();
620 if (STATEMAP.find(ringtoneState_) != STATEMAP.end()) {
621 curState = STATEMAP.at(ringtoneState_);
622 }
623 }
624 napi_create_string_utf8(env, curState.c_str(), NAPI_AUTO_LENGTH, &result);
625
626 return result;
627 }
628
On(napi_env env,napi_callback_info info)629 napi_value RingtonePlayerNapi::On(napi_env env, napi_callback_info info)
630 {
631 const size_t requireArgc = 2;
632 size_t argc = 3;
633
634 napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
635 napi_value jsThis = nullptr;
636 napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
637 if (status != napi_ok) {
638 ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM, "system err");
639 }
640 if (argc < requireArgc) {
641 ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
642 }
643
644 napi_valuetype argvType = napi_undefined;
645 napi_typeof(env, argv[0], &argvType);
646 if (argvType != napi_string) {
647 ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
648 "incorrect parameter types: The type of eventType must be string");
649 }
650
651 std::string callbackName = RingtoneCommonNapi::GetStringArgument(env, argv[0]);
652 MEDIA_LOGI("RingtonePlayerNapi: On callbackName: %{public}s", callbackName.c_str());
653
654 napi_valuetype callbackFunction = napi_undefined;
655 if (argc == requireArgc) {
656 napi_typeof(env, argv[1], &callbackFunction);
657 if (callbackFunction != napi_function) {
658 ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
659 "incorrect parameter types: The type of callback must be function");
660 }
661 } else {
662 napi_valuetype paramArg1 = napi_undefined;
663 napi_typeof(env, argv[1], ¶mArg1);
664 napi_valuetype expectedValType = napi_number; // Default. Reset it with 'callbackName' if check, if required.
665 if (paramArg1 != expectedValType) {
666 ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
667 "incorrect parameter types: The parameter must be number");
668 }
669
670 const int32_t arg2 = 2;
671 napi_typeof(env, argv[arg2], &callbackFunction);
672 if (callbackFunction != napi_function) {
673 ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
674 "incorrect parameter types: The type of callback must be function");
675 }
676 }
677
678 return RegisterCallback(env, jsThis, argv, callbackName);
679 }
680
RegisterCallback(napi_env env,napi_value jsThis,napi_value * argv,const std::string & cbName)681 napi_value RingtonePlayerNapi::RegisterCallback(napi_env env, napi_value jsThis, napi_value* argv,
682 const std::string& cbName)
683 {
684 RingtonePlayerNapi *ringtonePlayerNapi = nullptr;
685 napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&ringtonePlayerNapi));
686 if (status != napi_ok) {
687 ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM, "system err");
688 }
689 if (ringtonePlayerNapi == nullptr) {
690 ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY, "no memory");
691 }
692 if (ringtonePlayerNapi->ringtonePlayer_ == nullptr) {
693 ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY, "no memory");
694 }
695
696 napi_value result = nullptr;
697 napi_get_undefined(env, &result);
698
699 if (!cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME)) {
700 result = RegisterRingtonePlayerCallback(env, argv, cbName, ringtonePlayerNapi);
701 } else {
702 bool unknownCallback = true;
703 if (unknownCallback) {
704 ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
705 "parameter verification failed: The param of type is not supported");
706 }
707 }
708
709 return result;
710 }
711
RegisterRingtonePlayerCallback(napi_env env,napi_value * argv,const std::string & cbName,RingtonePlayerNapi * ringtonePlayerNapi)712 napi_value RingtonePlayerNapi::RegisterRingtonePlayerCallback(napi_env env, napi_value* argv,
713 const std::string& cbName, RingtonePlayerNapi *ringtonePlayerNapi)
714 {
715 if (ringtonePlayerNapi->callbackNapi_ == nullptr) {
716 ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY, "no memory");
717 }
718
719 std::shared_ptr<RingtonePlayerCallbackNapi> cb =
720 std::static_pointer_cast<RingtonePlayerCallbackNapi>(ringtonePlayerNapi->callbackNapi_);
721 cb->SaveCallbackReference(cbName, argv[PARAM1]);
722
723 napi_value result = nullptr;
724 napi_get_undefined(env, &result);
725 return result;
726 }
727
Off(napi_env env,napi_callback_info info)728 napi_value RingtonePlayerNapi::Off(napi_env env, napi_callback_info info)
729 {
730 const size_t requireArgc = 2;
731 size_t argc = 3;
732
733 napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
734 napi_value jsThis = nullptr;
735 napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
736 if (status != napi_ok) {
737 ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM, "system err");
738 }
739 if (argc > requireArgc) {
740 ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
741 }
742
743 napi_valuetype callbackNameType = napi_undefined;
744 napi_typeof(env, argv[0], &callbackNameType);
745 if (callbackNameType != napi_string) {
746 ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
747 "incorrect parameter types: The type of eventType must be string");
748 }
749
750 string callbackName = RingtoneCommonNapi::GetStringArgument(env, argv[0]);
751 MEDIA_LOGI("Off callbackName: %{public}s", callbackName.c_str());
752
753 return UnregisterCallback(env, jsThis, callbackName);
754 }
755
UnregisterCallback(napi_env env,napi_value jsThis,const string & cbName)756 napi_value RingtonePlayerNapi::UnregisterCallback(napi_env env, napi_value jsThis, const string& cbName)
757 {
758 RingtonePlayerNapi *ringtonePlayerNapi = nullptr;
759 napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&ringtonePlayerNapi));
760 if (status != napi_ok) {
761 ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM, "system err");
762 }
763 if (ringtonePlayerNapi == nullptr) {
764 ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY, "no memory");
765 }
766 if (ringtonePlayerNapi->ringtonePlayer_ == nullptr) {
767 ThrowErrorAndReturn(env, NAPI_ERR_NO_MEMORY, "no memory");
768 }
769
770 if (!cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME)) {
771 UnregisterRingtonePlayerCallback(ringtonePlayerNapi, cbName);
772 } else {
773 bool unknownCallback = true;
774 if (unknownCallback) {
775 ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
776 "parameter verification failed: The param of type is not supported");
777 }
778 }
779
780 napi_value result = nullptr;
781 napi_get_undefined(env, &result);
782 return result;
783 }
784
UnregisterRingtonePlayerCallback(RingtonePlayerNapi * ringtonePlayerNapi,const string & cbName)785 void RingtonePlayerNapi::UnregisterRingtonePlayerCallback(RingtonePlayerNapi *ringtonePlayerNapi, const string& cbName)
786 {
787 CHECK_AND_RETURN_LOG(ringtonePlayerNapi->callbackNapi_ != nullptr, "ringtonePlayerCallbackNapi is nullptr");
788
789 shared_ptr<RingtonePlayerCallbackNapi> cb =
790 static_pointer_cast<RingtonePlayerCallbackNapi>(ringtonePlayerNapi->callbackNapi_);
791 cb->RemoveCallbackReference(cbName);
792 }
793 } // namespace Media
794 } // namespace OHOS