• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "media_errors.h"
17 #include "media_log.h"
18 #include "ability.h"
19 #include "napi_base_context.h"
20 #include "soundpool_napi.h"
21 #ifndef CROSS_PLATFORM
22 #include "ipc_skeleton.h"
23 #include "tokenid_kit.h"
24 #endif
25 
26 namespace {
27     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_SOUNDPOOL, "SoundPoolNapi"};
28 }
29 
30 namespace OHOS {
31 namespace Media {
32 int32_t SoundPoolNapi::maxStreams = 0;
33 AudioStandard::AudioRendererInfo SoundPoolNapi::rendererInfo;
34 thread_local napi_ref SoundPoolNapi::constructor_ = nullptr;
35 thread_local napi_ref SoundPoolNapi::constructorParallel_ = nullptr;
36 const std::string CLASS_NAME = "SoundPool";
37 const std::string CLASS_NAME_PARALLE = "ParallelSoundPool";
38 
~SoundPoolNapi()39 SoundPoolNapi::~SoundPoolNapi()
40 {
41     MEDIA_LOGI("SoundPoolNapi::~SoundPoolNapi");
42 }
43 
Init(napi_env env,napi_value exports)44 napi_value SoundPoolNapi::Init(napi_env env, napi_value exports)
45 {
46     napi_property_descriptor staticProperty[] = {
47         DECLARE_NAPI_STATIC_FUNCTION("createSoundPool", JsCreateSoundPool),
48         DECLARE_NAPI_STATIC_FUNCTION("createParallelSoundPool", JsCreateParallelSoundPool),
49     };
50 
51     napi_property_descriptor properties[] = {
52         DECLARE_NAPI_FUNCTION("load", JsLoad),
53         DECLARE_NAPI_FUNCTION("play", JsPlay),
54         DECLARE_NAPI_FUNCTION("stop", JsStop),
55         DECLARE_NAPI_FUNCTION("setLoop", JsSetLoop),
56         DECLARE_NAPI_FUNCTION("setPriority", JsSetPriority),
57         DECLARE_NAPI_FUNCTION("setRate", JsSetRate),
58         DECLARE_NAPI_FUNCTION("setVolume", JsSetVolume),
59         DECLARE_NAPI_FUNCTION("unload", JsUnload),
60         DECLARE_NAPI_FUNCTION("release", JsRelease),
61         DECLARE_NAPI_FUNCTION("on", JsSetOnCallback),
62         DECLARE_NAPI_FUNCTION("off", JsClearOnCallback),
63     };
64 
65     napi_value constructor = nullptr;
66     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
67         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
68     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define SoundPool class");
69 
70     status = napi_create_reference(env, constructor, 1, &constructor_);
71     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
72 
73     status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
74     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
75 
76     napi_value constructorParallel = nullptr;
77     status = napi_define_class(env, CLASS_NAME_PARALLE.c_str(), NAPI_AUTO_LENGTH, ConstructorParallel,
78         nullptr, sizeof(properties) / sizeof(properties[0]), properties, &constructorParallel);
79     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define ParallelSoundPool class");
80 
81     status = napi_create_reference(env, constructorParallel, 1, &constructorParallel_);
82     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructorParallel");
83 
84     status = napi_set_named_property(env, exports, CLASS_NAME_PARALLE.c_str(), constructorParallel);
85     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructorParallel");
86 
87     status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
88     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
89 
90     MEDIA_LOGD("Init success");
91     return exports;
92 }
93 
Constructor(napi_env env,napi_callback_info info)94 napi_value SoundPoolNapi::Constructor(napi_env env, napi_callback_info info)
95 {
96     MEDIA_LOGI("Constructor enter");
97     napi_value result = nullptr;
98     napi_get_undefined(env, &result);
99 
100     size_t argCount = 0;
101     napi_value jsThis = nullptr;
102     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
103     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
104 
105     SoundPoolNapi *soundPoolNapi = new(std::nothrow) SoundPoolNapi();
106     CHECK_AND_RETURN_RET_LOG(soundPoolNapi != nullptr, result, "No memory!");
107 
108     soundPoolNapi->env_ = env;
109     soundPoolNapi->soundPool_ = SoundPoolFactory::CreateSoundPool(maxStreams, rendererInfo);
110     if (soundPoolNapi->soundPool_ == nullptr) {
111         delete soundPoolNapi;
112         MEDIA_LOGE("failed to CreateSoundPool");
113         return result;
114     }
115 
116     if (soundPoolNapi->callbackNapi_ == nullptr && soundPoolNapi->soundPool_ != nullptr) {
117         soundPoolNapi->callbackNapi_ = std::make_shared<SoundPoolCallBackNapi>(env);
118         (void)soundPoolNapi->soundPool_->SetSoundPoolCallback(soundPoolNapi->callbackNapi_);
119     }
120 
121     status = napi_wrap(env, jsThis, reinterpret_cast<void *>(soundPoolNapi),
122         SoundPoolNapi::Destructor, nullptr, nullptr);
123     if (status != napi_ok) {
124         delete soundPoolNapi;
125         MEDIA_LOGE("Failed to warp native instance!");
126         return result;
127     }
128     MEDIA_LOGI("Constructor success");
129     return jsThis;
130 }
131 
ConstructorParallel(napi_env env,napi_callback_info info)132 napi_value SoundPoolNapi::ConstructorParallel(napi_env env, napi_callback_info info)
133 {
134     MEDIA_LOGI("ConstructorParallel enter");
135     napi_value result = nullptr;
136     napi_get_undefined(env, &result);
137 
138     size_t argCount = 0;
139     napi_value jsThis = nullptr;
140     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
141     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
142 
143     SoundPoolNapi *soundPoolNapi = new(std::nothrow) SoundPoolNapi();
144     CHECK_AND_RETURN_RET_LOG(soundPoolNapi != nullptr, result, "No memory!");
145 
146     soundPoolNapi->env_ = env;
147     soundPoolNapi->soundPool_ = SoundPoolFactory::CreateParallelSoundPool(maxStreams, rendererInfo);
148     if (soundPoolNapi->soundPool_ == nullptr) {
149         delete soundPoolNapi;
150         MEDIA_LOGE("failed to CreateParallelSoundPool");
151         return result;
152     }
153 
154     if (soundPoolNapi->callbackNapi_ == nullptr && soundPoolNapi->soundPool_ != nullptr) {
155         soundPoolNapi->callbackNapi_ = std::make_shared<SoundPoolCallBackNapi>(env);
156         (void)soundPoolNapi->soundPool_->SetSoundPoolCallback(soundPoolNapi->callbackNapi_);
157     }
158 
159     status = napi_wrap(env, jsThis, reinterpret_cast<void *>(soundPoolNapi),
160         SoundPoolNapi::Destructor, nullptr, nullptr);
161     if (status != napi_ok) {
162         delete soundPoolNapi;
163         MEDIA_LOGE("Failed to warp native instance!");
164         return result;
165     }
166     MEDIA_LOGI("ConstructorParallel success");
167     return jsThis;
168 }
169 
Destructor(napi_env env,void * nativeObject,void * finalize)170 void SoundPoolNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
171 {
172     (void)env;
173     (void)finalize;
174     if (nativeObject != nullptr) {
175         SoundPoolNapi *napi = reinterpret_cast<SoundPoolNapi *>(nativeObject);
176         napi->callbackNapi_ = nullptr;
177 
178         if (napi->soundPool_) {
179             napi->soundPool_->Release();
180             napi->soundPool_ = nullptr;
181         }
182         delete napi;
183     }
184     MEDIA_LOGD("Destructor success");
185 }
186 
JsCreateSoundPool(napi_env env,napi_callback_info info)187 napi_value SoundPoolNapi::JsCreateSoundPool(napi_env env, napi_callback_info info)
188 {
189     MediaTrace trace("SoundPool::JsCreateSoundPool");
190     MEDIA_LOGI("SoundPoolNapi::JsCreateSoundPool");
191     napi_value result = nullptr;
192     napi_get_undefined(env, &result);
193 
194     // get args
195     napi_value jsThis = nullptr;
196     napi_value args[PARAM3] = { nullptr };
197     size_t argCount = PARAM3;
198     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
199     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
200 
201     // get create soundpool Parameter
202     status = GetJsInstanceWithParameter(env, args, PARAM3);
203     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to Get InstanceWithParameter");
204 
205     std::unique_ptr<SoundPoolAsyncContext> asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
206 
207     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM2]);
208     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
209     asyncCtx->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
210     asyncCtx->ctorFlag = true;
211 
212     SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
213     return result;
214 }
215 
JsCreateParallelSoundPool(napi_env env,napi_callback_info info)216 napi_value SoundPoolNapi::JsCreateParallelSoundPool(napi_env env, napi_callback_info info)
217 {
218     MediaTrace trace("SoundPool::JsCreateParallelSoundPool");
219     MEDIA_LOGI("SoundPoolNapi::JsCreateParallelSoundPool");
220     napi_value result = nullptr;
221     napi_get_undefined(env, &result);
222 
223     // get args
224     napi_value jsThis = nullptr;
225     napi_value args[PARAM2] = { nullptr };
226     size_t argCount = PARAM2;
227     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
228     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
229 
230     // get create soundpool Parameter
231     status = GetJsInstanceWithParameter(env, args, PARAM2);
232     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to Get InstanceWithParameter");
233 
234     std::unique_ptr<SoundPoolAsyncContext> asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
235 
236     asyncCtx->deferred = CommonNapi::CreatePromise(env, nullptr, result);
237     asyncCtx->JsResult = std::make_unique<MediaJsResultInstance>(constructorParallel_);
238     asyncCtx->ctorFlag = true;
239     if (!IsSystemApp()) {
240         asyncCtx->SignError(MSERR_EXT_API9_PERMISSION_DENIED, "failed to get without permission");
241     }
242 
243     SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
244     return result;
245 }
246 
JsLoad(napi_env env,napi_callback_info info)247 napi_value SoundPoolNapi::JsLoad(napi_env env, napi_callback_info info)
248 {
249     MediaTrace trace("SoundPool::JsLoad");
250     MEDIA_LOGI("SoundPoolNapi::JsLoad");
251     size_t argCount = PARAM4;
252     napi_value args[PARAM4] = { nullptr };
253     napi_value result = nullptr;
254     napi_get_undefined(env, &result);
255 
256     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
257     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
258     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
259     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
260     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
261 
262     if (argCount == PARAM4) {
263         asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM3]);
264     } else {
265         asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM1]);
266     }
267     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
268     napi_value resource = nullptr;
269     napi_create_string_utf8(env, "JsLoad", NAPI_AUTO_LENGTH, &resource);
270     if (asyncCtx->napi->ParserLoadOptionFromJs(asyncCtx, env, args, argCount) == MSERR_OK) {
271         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
272             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
273             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
274             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
275             int32_t soundId;
276             if (asyncCtx->url_.empty()) {
277                 soundId = asyncCtx->soundPool_->Load(asyncCtx->fd_, asyncCtx->offset_, asyncCtx->length_);
278             } else {
279                 soundId = asyncCtx->soundPool_->Load(asyncCtx->url_);
280             }
281             if (soundId < 0) {
282                 asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "load sound failed");
283             } else {
284                 asyncCtx->JsResult = std::make_unique<MediaJsResultInt>(soundId);
285             }
286             MEDIA_LOGI("The js thread of load finishes execution and returns, soundId: %{public}d", soundId);
287         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
288         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
289         asyncCtx.release();
290     } else {
291         SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
292     }
293     return result;
294 }
295 
JsPlay(napi_env env,napi_callback_info info)296 napi_value SoundPoolNapi::JsPlay(napi_env env, napi_callback_info info)
297 {
298     MediaTrace trace("SoundPool::JsPlay");
299     MEDIA_LOGI("SoundPoolNapi::JsPlay");
300     size_t argCount = PARAM3;
301     napi_value args[PARAM3] = { nullptr };
302 
303     napi_value result = nullptr;
304     napi_get_undefined(env, &result);
305 
306     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
307     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
308     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
309     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
310     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
311 
312     if (argCount == PARAM3) {
313         asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM2]);
314     } else {
315         asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM1]);
316     }
317     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
318     napi_value resource = nullptr;
319     napi_create_string_utf8(env, "JsPlay", NAPI_AUTO_LENGTH, &resource);
320     if (asyncCtx->napi->ParserPlayOptionFromJs(asyncCtx, env, args, argCount) == MSERR_OK) {
321         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
322             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
323             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
324             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
325             int32_t streamId = asyncCtx->soundPool_->Play(asyncCtx->soundId_, asyncCtx->playParameters_);
326             if (streamId < 0) {
327                 asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "play sound failed");
328             } else {
329                 asyncCtx->JsResult = std::make_unique<MediaJsResultInt>(streamId);
330             }
331             MEDIA_LOGI("The js thread of play finishes execution and returns, streamId: %{public}d", streamId);
332         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
333         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
334         asyncCtx.release();
335     } else {
336         SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
337     }
338     return result;
339 }
340 
JsStop(napi_env env,napi_callback_info info)341 napi_value SoundPoolNapi::JsStop(napi_env env, napi_callback_info info)
342 {
343     MediaTrace trace("SoundPool::JsStop");
344     MEDIA_LOGI("SoundPoolNapi::JsStop");
345     size_t argCount = PARAM2;
346     napi_value args[PARAM2] = { nullptr };
347 
348     napi_value result = nullptr;
349     napi_get_undefined(env, &result);
350 
351     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
352     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
353     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
354     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
355     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
356 
357     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM1]);
358     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
359     napi_status status = napi_get_value_int32(env, args[PARAM0], &asyncCtx->streamId_);
360     if (status != napi_ok || asyncCtx->streamId_ <= 0) {
361         asyncCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "stop streamId failed, invaild value");
362     }
363     napi_value resource = nullptr;
364     napi_create_string_utf8(env, "JsStop", NAPI_AUTO_LENGTH, &resource);
365     if (status == napi_ok && asyncCtx->streamId_ > 0) {
366         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
367             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
368             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
369             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
370             int32_t ret = asyncCtx->soundPool_->Stop(asyncCtx->streamId_);
371             if (ret != MSERR_OK) {
372                 asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "stop streamId failed");
373             }
374             MEDIA_LOGI("The js thread of stop finishes execution and returns");
375         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
376         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
377         asyncCtx.release();
378     } else {
379         SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
380     }
381     return result;
382 }
383 
JsSetLoop(napi_env env,napi_callback_info info)384 napi_value SoundPoolNapi::JsSetLoop(napi_env env, napi_callback_info info)
385 {
386     MediaTrace trace("SoundPool::JsSetLoop");
387     MEDIA_LOGI("SoundPoolNapi::JsSetLoop");
388     size_t argCount = PARAM3;
389     napi_value args[PARAM3] = { nullptr };
390 
391     napi_value result = nullptr;
392     napi_get_undefined(env, &result);
393 
394     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
395     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
396     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
397     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
398     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
399 
400     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM2]);
401     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
402     napi_status status = napi_get_value_int32(env, args[PARAM0], &asyncCtx->streamId_);
403     if (status != napi_ok || asyncCtx->streamId_ <= 0) {
404         asyncCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "SetLoop streamId failed,invaild value");
405     }
406     status = napi_get_value_int32(env, args[PARAM1], &asyncCtx->loop_);
407     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "failed to setloop id");
408 
409     napi_value resource = nullptr;
410     napi_create_string_utf8(env, "JsSetLoop", NAPI_AUTO_LENGTH, &resource);
411     if (status == napi_ok && asyncCtx->streamId_ > 0) {
412         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
413             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
414             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
415             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
416             int32_t ret = asyncCtx->soundPool_->SetLoop(asyncCtx->streamId_, asyncCtx->loop_);
417             if (ret != MSERR_OK) {
418                 asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "setLoop streamId failed");
419             }
420             MEDIA_LOGI("The js thread of SetLoop finishes execution and returns");
421         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
422         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
423         asyncCtx.release();
424     } else {
425         SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
426     }
427     return result;
428 }
429 
JsSetPriority(napi_env env,napi_callback_info info)430 napi_value SoundPoolNapi::JsSetPriority(napi_env env, napi_callback_info info)
431 {
432     MediaTrace trace("SoundPool::JsSetPriority");
433     MEDIA_LOGI("SoundPoolNapi::JsSetPriority");
434     size_t argCount = PARAM3;
435     napi_value args[PARAM3] = { nullptr };
436 
437     napi_value result = nullptr;
438     napi_get_undefined(env, &result);
439 
440     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
441     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
442     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
443     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
444     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
445 
446     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM2]);
447     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
448     napi_status status = napi_get_value_int32(env, args[PARAM0], &asyncCtx->streamId_);
449     if (status != napi_ok || asyncCtx->streamId_ <= 0) {
450         asyncCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "SetPriority streamId failed");
451     }
452     status = napi_get_value_int32(env, args[PARAM1], &asyncCtx->priority_);
453     if (status != napi_ok || asyncCtx->priority_ < 0) {
454         asyncCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "SetPriority priority failed");
455     }
456 
457     napi_value resource = nullptr;
458     napi_create_string_utf8(env, "JsSetPriority", NAPI_AUTO_LENGTH, &resource);
459     if (status == napi_ok && asyncCtx->streamId_ > 0) {
460         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
461             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
462             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
463             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
464             int32_t ret = asyncCtx->soundPool_->SetPriority(asyncCtx->streamId_, asyncCtx->priority_);
465             if (ret != MSERR_OK) {
466                 asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "SetPriority streamId failed");
467             }
468             MEDIA_LOGI("The js thread of SetPriority finishes execution and returns");
469         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
470         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
471         asyncCtx.release();
472     } else {
473         SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
474     }
475     return result;
476 }
477 
JsSetRate(napi_env env,napi_callback_info info)478 napi_value SoundPoolNapi::JsSetRate(napi_env env, napi_callback_info info)
479 {
480     MediaTrace trace("SoundPool::JsSetRate");
481     MEDIA_LOGI("SoundPoolNapi::JsSetRate");
482     size_t argCount = PARAM3;
483     napi_value args[PARAM3] = { nullptr };
484 
485     napi_value result = nullptr;
486     napi_get_undefined(env, &result);
487 
488     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
489     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
490     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
491     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
492     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
493 
494     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM2]);
495     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
496     napi_value resource = nullptr;
497     napi_create_string_utf8(env, "JsSetRate", NAPI_AUTO_LENGTH, &resource);
498     if (asyncCtx->napi->ParserRateOptionFromJs(asyncCtx, env, args) == MSERR_OK) {
499         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
500             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
501             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
502             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
503             int32_t ret = asyncCtx->soundPool_->SetRate(asyncCtx->streamId_, asyncCtx->renderRate_);
504             if (ret != MSERR_OK) {
505                 asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "SetRate streamId failed");
506             }
507             MEDIA_LOGI("The js thread of SetRate finishes execution and returns");
508         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
509         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
510         asyncCtx.release();
511     } else {
512         SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
513     }
514     return result;
515 }
516 
JsSetVolume(napi_env env,napi_callback_info info)517 napi_value SoundPoolNapi::JsSetVolume(napi_env env, napi_callback_info info)
518 {
519     MediaTrace trace("SoundPool::JsSetVolume");
520     MEDIA_LOGI("SoundPoolNapi::JsSetVolume");
521     size_t argCount = PARAM4;
522     napi_value args[PARAM4] = { nullptr };
523 
524     napi_value result = nullptr;
525     napi_get_undefined(env, &result);
526 
527     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
528     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
529     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
530     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
531     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
532 
533     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM3]);
534     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
535     napi_value resource = nullptr;
536     napi_create_string_utf8(env, "JsSetVolume", NAPI_AUTO_LENGTH, &resource);
537     if (asyncCtx->napi->ParserVolumeOptionFromJs(asyncCtx, env, args) == MSERR_OK) {
538         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
539             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
540             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
541             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
542             int32_t ret = asyncCtx->soundPool_->SetVolume(asyncCtx->streamId_,
543                 asyncCtx->leftVolume_, asyncCtx->rightVolume_);
544             if (ret != MSERR_OK) {
545                 asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "setVolume streamId failed");
546             }
547             MEDIA_LOGI("The js thread of SetVolume finishes execution and returns");
548         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
549         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
550         asyncCtx.release();
551     } else {
552         SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
553     }
554     return result;
555 }
556 
JsUnload(napi_env env,napi_callback_info info)557 napi_value SoundPoolNapi::JsUnload(napi_env env, napi_callback_info info)
558 {
559     MediaTrace trace("SoundPool::JsUnload");
560     MEDIA_LOGI("SoundPoolNapi::JsUnload");
561     size_t argCount = PARAM2;
562     napi_value args[PARAM2] = { nullptr };
563 
564     napi_value result = nullptr;
565     napi_get_undefined(env, &result);
566 
567     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
568     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
569     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
570     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
571     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
572 
573     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM1]);
574     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
575     napi_status status = napi_get_value_int32(env, args[PARAM0], &asyncCtx->soundId_);
576     if (status != napi_ok || asyncCtx->soundId_ <= 0) {
577         asyncCtx->SignError(MSERR_EXT_API9_IO, "unLoad failed,inavild value");
578     }
579 
580     napi_value resource = nullptr;
581     napi_create_string_utf8(env, "JsUnload", NAPI_AUTO_LENGTH, &resource);
582     if (status == napi_ok && asyncCtx->soundId_ > 0) {
583         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
584             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
585             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
586             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
587             int32_t ret = asyncCtx->soundPool_->Unload(asyncCtx->soundId_);
588             if (ret != MSERR_OK) {
589                 asyncCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "unLoad soundID failed");
590             }
591             MEDIA_LOGI("The js thread of Unload finishes execution and returns, soundID: %{public}d",
592                 asyncCtx->soundId_);
593         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
594         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
595         asyncCtx.release();
596     } else {
597         SoundPoolNapi::SendCompleteEvent(env, std::move(asyncCtx));
598     }
599     return result;
600 }
601 
JsRelease(napi_env env,napi_callback_info info)602 napi_value SoundPoolNapi::JsRelease(napi_env env, napi_callback_info info)
603 {
604     MediaTrace trace("SoundPool::JsRelease");
605     MEDIA_LOGI("SoundPoolNapi::JsRelease");
606     size_t argCount = PARAM1;
607     napi_value args[PARAM1] = { nullptr };
608 
609     napi_value result = nullptr;
610     napi_get_undefined(env, &result);
611 
612     auto asyncCtx = std::make_unique<SoundPoolAsyncContext>(env);
613     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get SoundPoolAsyncContext");
614     asyncCtx->napi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
615     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
616     asyncCtx->soundPool_ = asyncCtx->napi->soundPool_;
617     asyncCtx->callbackNapi_ = asyncCtx->napi->callbackNapi_;
618 
619     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM0]);
620     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
621 
622     napi_value resource = nullptr;
623     napi_create_string_utf8(env, "JsRelease", NAPI_AUTO_LENGTH, &resource);
624     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
625         SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
626         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
627         CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
628         int32_t ret = asyncCtx->soundPool_->Release();
629         CHECK_AND_RETURN_LOG(ret == MSERR_OK, "Release failed!");
630         CHECK_AND_RETURN_LOG(asyncCtx->callbackNapi_ != nullptr, "release callbackNapi_ is nullptr!");
631         asyncCtx->napi->CancelCallback(asyncCtx->callbackNapi_);
632         MEDIA_LOGI("The js thread of JsRelease finishes execution and returns");
633     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
634     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
635     asyncCtx.release();
636 
637     return result;
638 }
639 
JsSetOnCallback(napi_env env,napi_callback_info info)640 napi_value SoundPoolNapi::JsSetOnCallback(napi_env env, napi_callback_info info)
641 {
642     MediaTrace trace("SoundPool::JsSetOnCallback");
643     MEDIA_LOGI("SoundPoolNapi::JsSetOnCallback");
644     napi_value result = nullptr;
645     napi_get_undefined(env, &result);
646 
647     size_t argCount = 2;
648     napi_value args[2] = { nullptr, nullptr };
649     SoundPoolNapi *soundPoolNapi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
650     CHECK_AND_RETURN_RET_LOG(soundPoolNapi != nullptr, result, "Failed to retrieve instance");
651 
652     napi_valuetype valueType0 = napi_undefined;
653     napi_valuetype valueType1 = napi_undefined;
654     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string ||
655         napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
656         soundPoolNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
657         return result;
658     }
659 
660     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
661     MEDIA_LOGI("set callbackName: %{public}s", callbackName.c_str());
662     if (callbackName != SoundPoolEvent::EVENT_LOAD_COMPLETED && callbackName != SoundPoolEvent::EVENT_PLAY_FINISHED &&
663         callbackName != SoundPoolEvent::EVENT_PLAY_FINISHED_WITH_STREAM_ID &&
664         callbackName != SoundPoolEvent::EVENT_ERROR && callbackName != SoundPoolEvent::EVENT_ERROR_OCCURRED) {
665         soundPoolNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
666         return result;
667     }
668 
669     napi_ref ref = nullptr;
670     napi_status status = napi_create_reference(env, args[1], 1, &ref);
671     CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
672 
673     std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
674     soundPoolNapi->SetCallbackReference(callbackName, autoRef);
675 
676     MEDIA_LOGI("JsSetOnCallback callbackName: %{public}s success", callbackName.c_str());
677     return result;
678 }
679 
JsClearOnCallback(napi_env env,napi_callback_info info)680 napi_value SoundPoolNapi::JsClearOnCallback(napi_env env, napi_callback_info info)
681 {
682     MediaTrace trace("SoundPool::JsClearOnCallback");
683     MEDIA_LOGI("SoundPoolNapi::JsClearOnCallback");
684     napi_value result = nullptr;
685     napi_get_undefined(env, &result);
686 
687     size_t argCount = 1;
688     napi_value args[1] = { nullptr };
689     SoundPoolNapi *soundPoolNapi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
690     CHECK_AND_RETURN_RET_LOG(soundPoolNapi != nullptr, result, "Failed to retrieve instance");
691 
692     napi_valuetype valueType0 = napi_undefined;
693     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
694         soundPoolNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
695         return result;
696     }
697 
698     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
699     if (callbackName != SoundPoolEvent::EVENT_LOAD_COMPLETED && callbackName != SoundPoolEvent::EVENT_PLAY_FINISHED &&
700         callbackName != SoundPoolEvent::EVENT_PLAY_FINISHED_WITH_STREAM_ID &&
701         callbackName != SoundPoolEvent::EVENT_ERROR && callbackName != SoundPoolEvent::EVENT_ERROR_OCCURRED) {
702         soundPoolNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
703         return result;
704     }
705 
706     soundPoolNapi->CancelCallbackReference(callbackName);
707 
708     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsClearOnCallback success", FAKE_POINTER(soundPoolNapi));
709     return result;
710 }
711 
GetJsInstanceAndArgs(napi_env env,napi_callback_info info,size_t & argCount,napi_value * args)712 SoundPoolNapi* SoundPoolNapi::GetJsInstanceAndArgs(napi_env env, napi_callback_info info,
713     size_t &argCount, napi_value *args)
714 {
715     napi_value jsThis = nullptr;
716     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
717     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
718     MEDIA_LOGI("0x:%{public}06" PRIXPTR " instance argCount:%{public}zu", FAKE_POINTER(jsThis), argCount);
719 
720     SoundPoolNapi *soundPoolNapi = nullptr;
721 
722     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&soundPoolNapi));
723     CHECK_AND_RETURN_RET_LOG(status == napi_ok && soundPoolNapi != nullptr, nullptr, "failed to retrieve instance");
724 
725     return soundPoolNapi;
726 }
727 
GetJsInstanceWithParameter(napi_env env,napi_value * argv,int32_t argvLength)728 napi_status SoundPoolNapi::GetJsInstanceWithParameter(napi_env env, napi_value *argv, int32_t argvLength)
729 {
730     CHECK_AND_RETURN_RET_LOG(argvLength >= PARAM2, napi_invalid_arg, "invalid argvLength");
731 
732     napi_status status = napi_get_value_int32(env, argv[PARAM0], &maxStreams); // get maxStreams
733     CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "failed to get napi maxStreams");
734 
735     napi_value tempValue = nullptr;
736     int32_t intValue = {0};
737     status = napi_get_named_property(env, argv[PARAM1], "content", &tempValue);
738     if (status == napi_ok) {
739         napi_get_value_int32(env, tempValue, &intValue);
740         rendererInfo.contentType = static_cast<AudioStandard::ContentType>(intValue);
741     }
742 
743     status = napi_get_named_property(env, argv[PARAM1], "usage", &tempValue);
744     if (status == napi_ok) {
745         napi_get_value_int32(env, tempValue, &intValue);
746         rendererInfo.streamUsage = static_cast<AudioStandard::StreamUsage>(intValue);
747     }
748 
749     status = napi_get_named_property(env, argv[PARAM1], "rendererFlags", &tempValue);
750     if (status == napi_ok) {
751         napi_get_value_int32(env, tempValue, &(rendererInfo.rendererFlags));
752     }
753 
754     return status;
755 }
756 
ParserLoadOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> & asyncCtx,napi_env env,napi_value * argv,size_t argCount)757 int32_t SoundPoolNapi::ParserLoadOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> &asyncCtx,
758     napi_env env, napi_value *argv, size_t argCount)
759 {
760     int32_t ret = MSERR_OK;
761     MEDIA_LOGI("ParserLoadOptionFromJs argCount %{public}zu", argCount);
762     if ((argCount < PARAM3) && (argCount > 0)) {
763         asyncCtx->url_ = CommonNapi::GetStringArgument(env, argv[PARAM0]);
764         CHECK_AND_RETURN_RET(asyncCtx->url_ != "",
765             (asyncCtx->SoundPoolAsyncSignError(MSERR_OPEN_FILE_FAILED, "geturl", "url"), MSERR_OPEN_FILE_FAILED));
766     } else if ((argCount >= PARAM3) && (argCount < MAX_PARAM)) {
767         napi_status status = napi_get_value_int32(env, argv[PARAM0], &asyncCtx->fd_);
768         CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->fd_ > 0),
769             (asyncCtx->SoundPoolAsyncSignError(MSERR_OPEN_FILE_FAILED, "getfd", "fd"), MSERR_OPEN_FILE_FAILED));
770 
771         status = napi_get_value_int64(env, argv[PARAM1], &asyncCtx->offset_);
772         CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->offset_ >= 0),
773             (asyncCtx->SoundPoolAsyncSignError(MSERR_OPEN_FILE_FAILED, "getoffset", "offset"), MSERR_OPEN_FILE_FAILED));
774 
775         status = napi_get_value_int64(env, argv[PARAM2], &asyncCtx->length_);
776         CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->length_ > 0),
777             (asyncCtx->SoundPoolAsyncSignError(MSERR_OPEN_FILE_FAILED, "getlength", "length"), MSERR_OPEN_FILE_FAILED));
778     } else {
779         MEDIA_LOGI("Get Value error,return error:MSERR_INVALID_VAL");
780         return MSERR_INVALID_VAL;
781     }
782     return ret;
783 }
784 
GetAbilityContext(napi_env env)785 static std::shared_ptr<AbilityRuntime::Context> GetAbilityContext(napi_env env)
786 {
787     auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
788     if (ability == nullptr) {
789         MEDIA_LOGE("Failed to obtain ability in FA mode");
790         return nullptr;
791     }
792     auto faContext = ability->GetAbilityContext();
793     if (faContext == nullptr) {
794         MEDIA_LOGE("GetAbilityContext returned null in FA model");
795         return nullptr;
796     }
797     return faContext;
798 }
799 
ParserPlayOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> & asyncCtx,napi_env env,napi_value * argv,size_t argCount)800 int32_t SoundPoolNapi::ParserPlayOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> &asyncCtx,
801     napi_env env, napi_value *argv, size_t argCount)
802 {
803     int32_t ret = MSERR_OK;
804     MEDIA_LOGI("ParserPlayOptionFromJs argCount %{public}zu", argCount);
805     napi_status status = napi_get_value_int32(env, argv[PARAM0], &asyncCtx->soundId_);
806     CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->soundId_ > 0),
807         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getplaysoundId", "soundId"), MSERR_INVALID_VAL));
808 
809     CommonNapi::GetPropertyInt32(env, argv[PARAM1], "loop", asyncCtx->playParameters_.loop);
810     CommonNapi::GetPropertyInt32(env, argv[PARAM1], "rate", asyncCtx->playParameters_.rate);
811     double leftVolume;
812     ret = CommonNapi::GetPropertyDouble(env, argv[PARAM1], "leftVolume", leftVolume);
813     if (ret > 0) {
814         asyncCtx->playParameters_.leftVolume = static_cast<float>(leftVolume);
815     }
816     ret = CommonNapi::GetPropertyDouble(env, argv[PARAM1], "rightVolume", leftVolume);
817     if (ret > 0) {
818         asyncCtx->playParameters_.rightVolume = static_cast<float>(leftVolume);
819     }
820     CommonNapi::GetPropertyInt32(env, argv[PARAM1], "priority", asyncCtx->playParameters_.priority);
821     GetPropertyBool(env, argv[PARAM1], "parallelPlayFlag", asyncCtx->playParameters_.parallelPlayFlag);
822 
823     std::shared_ptr<AbilityRuntime::Context> abilityContext = GetAbilityContext(env);
824     if (abilityContext != nullptr) {
825         asyncCtx->playParameters_.cacheDir = abilityContext->GetCacheDir();
826     } else {
827         asyncCtx->playParameters_.cacheDir = "/data/storage/el2/base/temp";
828     }
829     MEDIA_LOGI("playParameters_ loop:%{public}d, rate:%{public}d, leftVolume:%{public}f, rightvolume:%{public}f,"
830         "priority:%{public}d, parallelPlayFlag:%{public}d", asyncCtx->playParameters_.loop,
831         asyncCtx->playParameters_.rate, asyncCtx->playParameters_.leftVolume,
832         asyncCtx->playParameters_.rightVolume, asyncCtx->playParameters_.priority,
833         asyncCtx->playParameters_.parallelPlayFlag);
834     return MSERR_OK;
835 }
836 
ParserRateOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> & asyncCtx,napi_env env,napi_value * argv)837 int32_t SoundPoolNapi::ParserRateOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> &asyncCtx,
838     napi_env env, napi_value *argv)
839 {
840     int32_t ret = MSERR_OK;
841     napi_status status = napi_get_value_int32(env, argv[PARAM0], &asyncCtx->streamId_);
842     CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->streamId_ > 0),
843         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getratestreamId", "streamId"), MSERR_INVALID_VAL));
844     int32_t rendderRate;
845     status = napi_get_value_int32(env, argv[PARAM1], &rendderRate);
846     CHECK_AND_RETURN_RET(status == napi_ok,
847         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getaudiorennderrate",
848         "audiorennderrate"), MSERR_INVALID_VAL));
849     asyncCtx->renderRate_ = static_cast<AudioStandard::AudioRendererRate>(rendderRate);
850 
851     return ret;
852 }
853 
ParserVolumeOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> & asyncCtx,napi_env env,napi_value * argv)854 int32_t SoundPoolNapi::ParserVolumeOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> &asyncCtx,
855     napi_env env, napi_value *argv)
856 {
857     int32_t ret = MSERR_OK;
858     napi_status status = napi_get_value_int32(env, argv[PARAM0], &asyncCtx->streamId_);
859     CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->streamId_ > 0),
860         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getvolumestreamId", "streamId"), MSERR_INVALID_VAL));
861     double tempvolume;
862     status = napi_get_value_double(env, argv[PARAM1], &tempvolume);
863     CHECK_AND_RETURN_RET(status == napi_ok,
864         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getleftvolme", "leftvolme"), MSERR_INVALID_VAL));
865     asyncCtx->leftVolume_ = static_cast<float>(tempvolume);
866 
867     status = napi_get_value_double(env, argv[PARAM2], &tempvolume);
868     CHECK_AND_RETURN_RET(status == napi_ok,
869         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getrightvolme", "rightvolme"), MSERR_INVALID_VAL));
870     asyncCtx->rightVolume_ = static_cast<float>(tempvolume);
871 
872     return ret;
873 }
874 
SendCompleteEvent(napi_env env,std::unique_ptr<SoundPoolAsyncContext> asyncCtx)875 void SoundPoolNapi::SendCompleteEvent(napi_env env, std::unique_ptr<SoundPoolAsyncContext> asyncCtx)
876 {
877     auto ret = MediaAsyncContext::SendCompleteEvent(env, asyncCtx.get(), napi_eprio_immediate);
878     if (ret != napi_status::napi_ok) {
879         MEDIA_LOGE("failed to SendEvent, ret = %{public}d", ret);
880     } else {
881         asyncCtx.release();
882     }
883 }
884 
ErrorCallback(int32_t errCode,const std::string & operate,const std::string & add)885 void SoundPoolNapi::ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add)
886 {
887     MEDIA_LOGE("failed to %{public}s, errCode = %{public}d", operate.c_str(), errCode);
888     CHECK_AND_RETURN_LOG(callbackNapi_ != nullptr, "soundpoolCb_ is nullptr!");
889     auto napiCb = std::static_pointer_cast<SoundPoolCallBackNapi>(callbackNapi_);
890 
891     MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
892     std::string msg = MSExtErrorAPI9ToString(err, operate, "") + add;
893     napiCb->SendErrorCallback(errCode, msg);
894 }
895 
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)896 void SoundPoolNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
897 {
898     eventCbMap_[callbackName] = ref;
899     CHECK_AND_RETURN_LOG(callbackNapi_ != nullptr, "soundpoolCb_ is nullptr!");
900     auto napiCb = std::static_pointer_cast<SoundPoolCallBackNapi>(callbackNapi_);
901     napiCb->SaveCallbackReference(callbackName, ref);
902 }
903 
CancelCallbackReference(const std::string & callbackName)904 void SoundPoolNapi::CancelCallbackReference(const std::string &callbackName)
905 {
906     CHECK_AND_RETURN_LOG(callbackNapi_ != nullptr, "soundpoolCb_ is nullptr!");
907     auto napiCb = std::static_pointer_cast<SoundPoolCallBackNapi>(callbackNapi_);
908     napiCb->CancelCallbackReference(callbackName);
909     eventCbMap_[callbackName] = nullptr;
910 }
911 
CancelCallback(std::shared_ptr<ISoundPoolCallback> callback)912 void SoundPoolNapi::CancelCallback(std::shared_ptr<ISoundPoolCallback> callback)
913 {
914     CHECK_AND_RETURN_LOG(callback != nullptr, "soundpoolCb_ is nullptr!");
915     auto napiCb = std::static_pointer_cast<SoundPoolCallBackNapi>(callback);
916     napiCb->ClearCallbackReference();
917 }
918 
GetPropertyBool(napi_env env,napi_value configObj,const std::string & type,bool & result)919 bool SoundPoolNapi::GetPropertyBool(napi_env env, napi_value configObj, const std::string &type, bool &result)
920 {
921     napi_value item = nullptr;
922     bool exist = false;
923     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
924     if (status != napi_ok || !exist) {
925         MEDIA_LOGE("can not find %{public}s property", type.c_str());
926         return false;
927     }
928 
929     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
930         MEDIA_LOGE("get %{public}s property fail", type.c_str());
931         return false;
932     }
933 
934     if (napi_get_value_bool(env, item, &result) != napi_ok) {
935         MEDIA_LOGE("get %{public}s property value fail", type.c_str());
936         return false;
937     }
938     return true;
939 }
940 
IsSystemApp()941 bool SoundPoolNapi::IsSystemApp()
942 {
943     static bool isSystemApp = false;
944 #ifndef CROSS_PLATFORM
945     static std::once_flag once;
946     std::call_once(once, [] {
947         uint64_t tokenId = IPCSkeleton::GetSelfTokenID();
948         isSystemApp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
949     });
950 #endif
951     return isSystemApp;
952 }
953 
GetRetInfo(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add="")954 RetInfo GetRetInfo(int32_t errCode, const std::string &operate, const std::string &param, const std::string &add = "")
955 {
956     MEDIA_LOGE("failed to %{public}s, param %{public}s, errCode = %{public}d", operate.c_str(), param.c_str(), errCode);
957     MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
958     if (errCode == MSERR_UNSUPPORT_VID_PARAMS) {
959         return RetInfo(err, "The video parameter is not supported. Please check the type and range.");
960     }
961 
962     if (errCode == MSERR_UNSUPPORT_AUD_PARAMS) {
963         return RetInfo(err, "The audio parameter is not supported. Please check the type and range.");
964     }
965 
966     std::string message;
967     if (err == MSERR_EXT_API9_INVALID_PARAMETER) {
968         message = MSExtErrorAPI9ToString(err, param, "") + add;
969     } else {
970         message = MSExtErrorAPI9ToString(err, operate, "") + add;
971     }
972 
973     MEDIA_LOGE("errCode: %{public}d, errMsg: %{public}s", err, message.c_str());
974     return RetInfo(err, message);
975 }
976 
SoundPoolAsyncSignError(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add)977 void SoundPoolAsyncContext::SoundPoolAsyncSignError(int32_t errCode, const std::string &operate,
978     const std::string &param, const std::string &add)
979 {
980     RetInfo retInfo = GetRetInfo(errCode, operate, param, add);
981     SignError(retInfo.first, retInfo.second);
982 }
983 } // namespace Media
984 } // namespace OHOS