• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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], &paramArg1);
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