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