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     asyncCtx->callbackNapi_ = asyncCtx->napi->callbackNapi_;
562 
563     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[PARAM0]);
564     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
565 
566     napi_value resource = nullptr;
567     napi_create_string_utf8(env, "JsRelease", NAPI_AUTO_LENGTH, &resource);
568         NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
569             SoundPoolAsyncContext* asyncCtx = reinterpret_cast<SoundPoolAsyncContext *>(data);
570             CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
571             CHECK_AND_RETURN_LOG(asyncCtx->soundPool_ != nullptr, "soundPool_ is nullptr!");
572             int32_t ret = asyncCtx->soundPool_->Release();
573             CHECK_AND_RETURN_LOG(ret == MSERR_OK, "Release failed!");
574             CHECK_AND_RETURN_LOG(asyncCtx->callbackNapi_ != nullptr, "release callbackNapi_ is nullptr!");
575             asyncCtx->napi->CancelCallback(asyncCtx->callbackNapi_);
576             MEDIA_LOGI("The js thread of JsRelease finishes execution and returns");
577         }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
578         NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
579     asyncCtx.release();
580 
581     return result;
582 }
583 
JsSetOnCallback(napi_env env,napi_callback_info info)584 napi_value SoundPoolNapi::JsSetOnCallback(napi_env env, napi_callback_info info)
585 {
586     MediaTrace trace("SoundPool::JsSetOnCallback");
587     MEDIA_LOGI("SoundPoolNapi::JsSetOnCallback");
588     napi_value result = nullptr;
589     napi_get_undefined(env, &result);
590 
591     size_t argCount = 2;
592     napi_value args[2] = { nullptr, nullptr };
593     SoundPoolNapi *soundPoolNapi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
594     CHECK_AND_RETURN_RET_LOG(soundPoolNapi != nullptr, result, "Failed to retrieve instance");
595 
596     napi_valuetype valueType0 = napi_undefined;
597     napi_valuetype valueType1 = napi_undefined;
598     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string ||
599         napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
600         soundPoolNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
601         return result;
602     }
603 
604     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
605     MEDIA_LOGI("set callbackName: %{public}s", callbackName.c_str());
606     if (callbackName != SoundPoolEvent::EVENT_LOAD_COMPLETED && callbackName != SoundPoolEvent::EVENT_PLAY_FINISHED &&
607         callbackName != SoundPoolEvent::EVENT_ERROR) {
608         soundPoolNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
609         return result;
610     }
611 
612     napi_ref ref = nullptr;
613     napi_status status = napi_create_reference(env, args[1], 1, &ref);
614     CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
615 
616     std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
617     soundPoolNapi->SetCallbackReference(callbackName, autoRef);
618 
619     MEDIA_LOGI("JsSetOnCallback callbackName: %{public}s success", callbackName.c_str());
620     return result;
621 }
622 
JsClearOnCallback(napi_env env,napi_callback_info info)623 napi_value SoundPoolNapi::JsClearOnCallback(napi_env env, napi_callback_info info)
624 {
625     MediaTrace trace("SoundPool::JsClearOnCallback");
626     MEDIA_LOGI("SoundPoolNapi::JsClearOnCallback");
627     napi_value result = nullptr;
628     napi_get_undefined(env, &result);
629 
630     size_t argCount = 1;
631     napi_value args[1] = { nullptr };
632     SoundPoolNapi *soundPoolNapi = SoundPoolNapi::GetJsInstanceAndArgs(env, info, argCount, args);
633     CHECK_AND_RETURN_RET_LOG(soundPoolNapi != nullptr, result, "Failed to retrieve instance");
634 
635     napi_valuetype valueType0 = napi_undefined;
636     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
637         soundPoolNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
638         return result;
639     }
640 
641     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
642     if (callbackName != SoundPoolEvent::EVENT_LOAD_COMPLETED && callbackName != SoundPoolEvent::EVENT_PLAY_FINISHED &&
643         callbackName != SoundPoolEvent::EVENT_ERROR) {
644         soundPoolNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
645         return result;
646     }
647 
648     soundPoolNapi->CancelCallbackReference(callbackName);
649 
650     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsClearOnCallback success", FAKE_POINTER(soundPoolNapi));
651     return result;
652 }
653 
GetJsInstanceAndArgs(napi_env env,napi_callback_info info,size_t & argCount,napi_value * args)654 SoundPoolNapi* SoundPoolNapi::GetJsInstanceAndArgs(napi_env env, napi_callback_info info,
655     size_t &argCount, napi_value *args)
656 {
657     napi_value jsThis = nullptr;
658     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
659     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
660     MEDIA_LOGI("0x:%{public}06" PRIXPTR " instance argCount:%{public}zu", FAKE_POINTER(jsThis), argCount);
661 
662     SoundPoolNapi *soundPoolNapi = nullptr;
663 
664     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&soundPoolNapi));
665     CHECK_AND_RETURN_RET_LOG(status == napi_ok && soundPoolNapi != nullptr, nullptr, "failed to retrieve instance");
666 
667     return soundPoolNapi;
668 }
669 
GetJsInstanceWithParameter(napi_env env,napi_value * argv)670 napi_status SoundPoolNapi::GetJsInstanceWithParameter(napi_env env, napi_value *argv)
671 {
672     napi_status status = napi_get_value_int32(env, argv[PARAM0], &maxStreams); // get maxStreams
673     CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "failed to get napi maxStreams");
674 
675     napi_value tempValue = nullptr;
676     int32_t intValue = {0};
677     status = napi_get_named_property(env, argv[PARAM1], "content", &tempValue);
678     if (status == napi_ok) {
679         napi_get_value_int32(env, tempValue, &intValue);
680         rendererInfo.contentType = static_cast<AudioStandard::ContentType>(intValue);
681     }
682 
683     status = napi_get_named_property(env, argv[PARAM1], "usage", &tempValue);
684     if (status == napi_ok) {
685         napi_get_value_int32(env, tempValue, &intValue);
686         rendererInfo.streamUsage = static_cast<AudioStandard::StreamUsage>(intValue);
687     }
688 
689     status = napi_get_named_property(env, argv[PARAM1], "rendererFlags", &tempValue);
690     if (status == napi_ok) {
691         napi_get_value_int32(env, tempValue, &(rendererInfo.rendererFlags));
692     }
693 
694     return status;
695 }
696 
ParserLoadOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> & asyncCtx,napi_env env,napi_value * argv,size_t argCount)697 int32_t SoundPoolNapi::ParserLoadOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> &asyncCtx,
698     napi_env env, napi_value *argv, size_t argCount)
699 {
700     int32_t ret = MSERR_OK;
701     MEDIA_LOGI("ParserLoadOptionFromJs argCount %{public}zu", argCount);
702     if ((argCount < PARAM3) && (argCount > 0)) {
703         asyncCtx->url_ = CommonNapi::GetStringArgument(env, argv[PARAM0]);
704         CHECK_AND_RETURN_RET(asyncCtx->url_ != "",
705             (asyncCtx->SoundPoolAsyncSignError(MSERR_OPEN_FILE_FAILED, "geturl", "url"), MSERR_OPEN_FILE_FAILED));
706     } else if ((argCount >= PARAM3) && (argCount < MAX_PARAM)) {
707         napi_status status = napi_get_value_int32(env, argv[PARAM0], &asyncCtx->fd_);
708         CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->fd_ > 0),
709             (asyncCtx->SoundPoolAsyncSignError(MSERR_OPEN_FILE_FAILED, "getfd", "fd"), MSERR_OPEN_FILE_FAILED));
710 
711         status = napi_get_value_int64(env, argv[PARAM1], &asyncCtx->offset_);
712         CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->offset_ >= 0),
713             (asyncCtx->SoundPoolAsyncSignError(MSERR_OPEN_FILE_FAILED, "getoffset", "offset"), MSERR_OPEN_FILE_FAILED));
714 
715         status = napi_get_value_int64(env, argv[PARAM2], &asyncCtx->length_);
716         CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->length_ > 0),
717             (asyncCtx->SoundPoolAsyncSignError(MSERR_OPEN_FILE_FAILED, "getlength", "length"), MSERR_OPEN_FILE_FAILED));
718     } else {
719         MEDIA_LOGI("Get Value error,return error:MSERR_INVALID_VAL");
720         return MSERR_INVALID_VAL;
721     }
722     return ret;
723 }
724 
GetAbilityContext(napi_env env)725 static std::shared_ptr<AbilityRuntime::Context> GetAbilityContext(napi_env env)
726 {
727     auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
728     if (ability == nullptr) {
729         MEDIA_LOGE("Failed to obtain ability in FA mode");
730         return nullptr;
731     }
732     auto faContext = ability->GetAbilityContext();
733     if (faContext == nullptr) {
734         MEDIA_LOGE("GetAbilityContext returned null in FA model");
735         return nullptr;
736     }
737     return faContext;
738 }
739 
ParserPlayOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> & asyncCtx,napi_env env,napi_value * argv,size_t argCount)740 int32_t SoundPoolNapi::ParserPlayOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> &asyncCtx,
741     napi_env env, napi_value *argv, size_t argCount)
742 {
743     int32_t ret = MSERR_OK;
744     MEDIA_LOGI("ParserPlayOptionFromJs argCount %{public}zu", argCount);
745     napi_status status = napi_get_value_int32(env, argv[PARAM0], &asyncCtx->soundId_);
746     CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->soundId_ > 0),
747         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getplaysoundId", "soundId"), MSERR_INVALID_VAL));
748 
749     CommonNapi::GetPropertyInt32(env, argv[PARAM1], "loop", asyncCtx->playParameters_.loop);
750     CommonNapi::GetPropertyInt32(env, argv[PARAM1], "rate", asyncCtx->playParameters_.rate);
751     double leftVolume;
752     ret = CommonNapi::GetPropertyDouble(env, argv[PARAM1], "leftVolume", leftVolume);
753     if (ret > 0) {
754         asyncCtx->playParameters_.leftVolume = static_cast<float>(leftVolume);
755     }
756     ret = CommonNapi::GetPropertyDouble(env, argv[PARAM1], "rightVolume", leftVolume);
757     if (ret > 0) {
758         asyncCtx->playParameters_.rightVolume = static_cast<float>(leftVolume);
759     }
760     CommonNapi::GetPropertyInt32(env, argv[PARAM1], "priority", asyncCtx->playParameters_.priority);
761     GetPropertyBool(env, argv[PARAM1], "parallelPlayFlag", asyncCtx->playParameters_.parallelPlayFlag);
762 
763     std::shared_ptr<AbilityRuntime::Context> abilityContext = GetAbilityContext(env);
764     if (abilityContext != nullptr) {
765         asyncCtx->playParameters_.cacheDir = abilityContext->GetCacheDir();
766     } else {
767         asyncCtx->playParameters_.cacheDir = "/data/storage/el2/base/temp";
768     }
769     MEDIA_LOGI("playParameters_ loop:%{public}d, rate:%{public}d, leftVolume:%{public}f, rightvolume:%{public}f,"
770         "priority:%{public}d, parallelPlayFlag:%{public}d", asyncCtx->playParameters_.loop,
771         asyncCtx->playParameters_.rate, asyncCtx->playParameters_.leftVolume,
772         asyncCtx->playParameters_.rightVolume, asyncCtx->playParameters_.priority,
773         asyncCtx->playParameters_.parallelPlayFlag);
774     return MSERR_OK;
775 }
776 
ParserRateOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> & asyncCtx,napi_env env,napi_value * argv)777 int32_t SoundPoolNapi::ParserRateOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> &asyncCtx,
778     napi_env env, napi_value *argv)
779 {
780     int32_t ret = MSERR_OK;
781     napi_status status = napi_get_value_int32(env, argv[PARAM0], &asyncCtx->streamId_);
782     CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->streamId_ > 0),
783         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getratestreamId", "streamId"), MSERR_INVALID_VAL));
784     int32_t rendderRate;
785     status = napi_get_value_int32(env, argv[PARAM1], &rendderRate);
786     CHECK_AND_RETURN_RET(status == napi_ok,
787         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getaudiorennderrate",
788         "audiorennderrate"), MSERR_INVALID_VAL));
789     asyncCtx->renderRate_ = static_cast<AudioStandard::AudioRendererRate>(rendderRate);
790 
791     return ret;
792 }
793 
ParserVolumeOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> & asyncCtx,napi_env env,napi_value * argv)794 int32_t SoundPoolNapi::ParserVolumeOptionFromJs(std::unique_ptr<SoundPoolAsyncContext> &asyncCtx,
795     napi_env env, napi_value *argv)
796 {
797     int32_t ret = MSERR_OK;
798     napi_status status = napi_get_value_int32(env, argv[PARAM0], &asyncCtx->streamId_);
799     CHECK_AND_RETURN_RET((status == napi_ok && asyncCtx->streamId_ > 0),
800         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getvolumestreamId", "streamId"), MSERR_INVALID_VAL));
801     double tempvolume;
802     status = napi_get_value_double(env, argv[PARAM1], &tempvolume);
803     CHECK_AND_RETURN_RET(status == napi_ok,
804         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getleftvolme", "leftvolme"), MSERR_INVALID_VAL));
805     asyncCtx->leftVolume_ = static_cast<float>(tempvolume);
806 
807     status = napi_get_value_double(env, argv[PARAM2], &tempvolume);
808     CHECK_AND_RETURN_RET(status == napi_ok,
809         (asyncCtx->SoundPoolAsyncSignError(MSERR_INVALID_VAL, "getrightvolme", "rightvolme"), MSERR_INVALID_VAL));
810     asyncCtx->rightVolume_ = static_cast<float>(tempvolume);
811 
812     return ret;
813 }
814 
ErrorCallback(int32_t errCode,const std::string & operate,const std::string & add)815 void SoundPoolNapi::ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add)
816 {
817     MEDIA_LOGE("failed to %{public}s, errCode = %{public}d", operate.c_str(), errCode);
818     CHECK_AND_RETURN_LOG(callbackNapi_ != nullptr, "soundpoolCb_ is nullptr!");
819     auto napiCb = std::static_pointer_cast<SoundPoolCallBackNapi>(callbackNapi_);
820 
821     MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
822     std::string msg = MSExtErrorAPI9ToString(err, operate, "") + add;
823     napiCb->SendErrorCallback(errCode, msg);
824 }
825 
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)826 void SoundPoolNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
827 {
828     eventCbMap_[callbackName] = ref;
829     CHECK_AND_RETURN_LOG(callbackNapi_ != nullptr, "soundpoolCb_ is nullptr!");
830     auto napiCb = std::static_pointer_cast<SoundPoolCallBackNapi>(callbackNapi_);
831     napiCb->SaveCallbackReference(callbackName, ref);
832 }
833 
CancelCallbackReference(const std::string & callbackName)834 void SoundPoolNapi::CancelCallbackReference(const std::string &callbackName)
835 {
836     CHECK_AND_RETURN_LOG(callbackNapi_ != nullptr, "soundpoolCb_ is nullptr!");
837     auto napiCb = std::static_pointer_cast<SoundPoolCallBackNapi>(callbackNapi_);
838     napiCb->CancelCallbackReference(callbackName);
839     eventCbMap_[callbackName] = nullptr;
840 }
841 
CancelCallback(std::shared_ptr<ISoundPoolCallback> callback)842 void SoundPoolNapi::CancelCallback(std::shared_ptr<ISoundPoolCallback> callback)
843 {
844     CHECK_AND_RETURN_LOG(callback != nullptr, "soundpoolCb_ is nullptr!");
845     auto napiCb = std::static_pointer_cast<SoundPoolCallBackNapi>(callback);
846     napiCb->ClearCallbackReference();
847 }
848 
GetPropertyBool(napi_env env,napi_value configObj,const std::string & type,bool & result)849 bool SoundPoolNapi::GetPropertyBool(napi_env env, napi_value configObj, const std::string &type, bool &result)
850 {
851     napi_value item = nullptr;
852     bool exist = false;
853     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
854     if (status != napi_ok || !exist) {
855         MEDIA_LOGE("can not find %{public}s property", type.c_str());
856         return false;
857     }
858 
859     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
860         MEDIA_LOGE("get %{public}s property fail", type.c_str());
861         return false;
862     }
863 
864     if (napi_get_value_bool(env, item, &result) != napi_ok) {
865         MEDIA_LOGE("get %{public}s property value fail", type.c_str());
866         return false;
867     }
868     return true;
869 }
870 
GetRetInfo(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add="")871 RetInfo GetRetInfo(int32_t errCode, const std::string &operate, const std::string &param, const std::string &add = "")
872 {
873     MEDIA_LOGE("failed to %{public}s, param %{public}s, errCode = %{public}d", operate.c_str(), param.c_str(), errCode);
874     MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
875     if (errCode == MSERR_UNSUPPORT_VID_PARAMS) {
876         return RetInfo(err, "The video parameter is not supported. Please check the type and range.");
877     }
878 
879     if (errCode == MSERR_UNSUPPORT_AUD_PARAMS) {
880         return RetInfo(err, "The audio parameter is not supported. Please check the type and range.");
881     }
882 
883     std::string message;
884     if (err == MSERR_EXT_API9_INVALID_PARAMETER) {
885         message = MSExtErrorAPI9ToString(err, param, "") + add;
886     } else {
887         message = MSExtErrorAPI9ToString(err, operate, "") + add;
888     }
889 
890     MEDIA_LOGE("errCode: %{public}d, errMsg: %{public}s", err, message.c_str());
891     return RetInfo(err, message);
892 }
893 
SoundPoolAsyncSignError(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add)894 void SoundPoolAsyncContext::SoundPoolAsyncSignError(int32_t errCode, const std::string &operate,
895     const std::string &param, const std::string &add)
896 {
897     RetInfo retInfo = GetRetInfo(errCode, operate, param, add);
898     SignError(retInfo.first, retInfo.second);
899 }
900 } // namespace Media
901 } // namespace OHOS