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