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