1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "audio_haptic_manager_napi.h"
17
18 #include "audio_haptic_player_napi.h"
19
20 #include "audio_haptic_log.h"
21
22 namespace {
23 /* Constants for array index */
24 const int32_t PARAM0 = 0;
25 const int32_t PARAM1 = 1;
26
27 /* Constants for array size */
28 const int32_t ARGS_ONE = 1;
29 const int32_t ARGS_TWO = 2;
30 const int32_t SIZE = 1024;
31
32 const int ERROR = -1;
33 const int SUCCESS = 0;
34
35 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "AudioHapticManagerNapi"};
36 }
37
38 namespace OHOS {
39 namespace Media {
40 thread_local napi_ref AudioHapticManagerNapi::sConstructor_ = nullptr;
41 thread_local napi_ref AudioHapticManagerNapi::sAudioLatencyMode_ = nullptr;
42 thread_local napi_ref AudioHapticManagerNapi::sAudioHapticType_ = nullptr;
43
AudioHapticManagerNapi()44 AudioHapticManagerNapi::AudioHapticManagerNapi()
45 : env_(nullptr), audioHapticMgrClient_(nullptr) {}
46
47 AudioHapticManagerNapi::~AudioHapticManagerNapi() = default;
48
AddNamedProperty(napi_env env,napi_value object,const std::string name,int32_t enumValue)49 napi_status AudioHapticManagerNapi::AddNamedProperty(napi_env env, napi_value object, const std::string name,
50 int32_t enumValue)
51 {
52 napi_status status;
53 napi_value napiValue;
54
55 status = napi_create_int32(env, enumValue, &napiValue);
56 if (status == napi_ok) {
57 status = napi_set_named_property(env, object, name.c_str(), napiValue);
58 }
59
60 return status;
61 }
62
CreateAudioLatencyModeObject(napi_env env)63 napi_value AudioHapticManagerNapi::CreateAudioLatencyModeObject(napi_env env)
64 {
65 napi_value result = nullptr;
66 napi_status status;
67 std::string propName;
68 int32_t refCount = 1;
69
70 status = napi_create_object(env, &result);
71 if (status == napi_ok) {
72 for (auto &iter: audioLatencyModeMap) {
73 propName = iter.first;
74 status = AddNamedProperty(env, result, propName, iter.second);
75 if (status != napi_ok) {
76 MEDIA_LOGE("CreateAudioLatencyModeObject: Failed to add named prop!");
77 break;
78 }
79 propName.clear();
80 }
81 if (status == napi_ok) {
82 status = napi_create_reference(env, result, refCount, &sAudioLatencyMode_);
83 if (status == napi_ok) {
84 return result;
85 }
86 }
87 }
88 napi_get_undefined(env, &result);
89
90 return result;
91 }
92
CreateAudioHapticTypeObject(napi_env env)93 napi_value AudioHapticManagerNapi::CreateAudioHapticTypeObject(napi_env env)
94 {
95 napi_value result = nullptr;
96 napi_status status = napi_create_object(env, &result);
97 if (status == napi_ok) {
98 std::string propName;
99 for (auto &iter: audioHapticTypeMap) {
100 propName = iter.first;
101 status = AddNamedProperty(env, result, propName, iter.second);
102 if (status != napi_ok) {
103 MEDIA_LOGE("CreateAudioHapticTypeObject: Failed to add named prop!");
104 break;
105 }
106 propName.clear();
107 }
108 if (status == napi_ok) {
109 int32_t refCount = 1;
110 status = napi_create_reference(env, result, refCount, &sAudioHapticType_);
111 if (status == napi_ok) {
112 return result;
113 }
114 }
115 }
116 napi_get_undefined(env, &result);
117
118 return result;
119 }
120
Init(napi_env env,napi_value exports)121 napi_value AudioHapticManagerNapi::Init(napi_env env, napi_value exports)
122 {
123 napi_status status;
124 napi_value ctorObj;
125 int32_t refCount = 1;
126
127 napi_property_descriptor audioHapticMgrProp[] = {
128 DECLARE_NAPI_FUNCTION("registerSource", RegisterSource),
129 DECLARE_NAPI_FUNCTION("unregisterSource", UnregisterSource),
130 DECLARE_NAPI_FUNCTION("setAudioLatencyMode", SetAudioLatencyMode),
131 DECLARE_NAPI_FUNCTION("setStreamUsage", SetStreamUsage),
132 DECLARE_NAPI_FUNCTION("createPlayer", CreatePlayer),
133 };
134
135 napi_property_descriptor staticProp[] = {
136 DECLARE_NAPI_STATIC_FUNCTION("getAudioHapticManager", GetAudioHapticManager),
137 DECLARE_NAPI_PROPERTY("AudioLatencyMode", CreateAudioLatencyModeObject(env)),
138 DECLARE_NAPI_PROPERTY("AudioHapticType", CreateAudioHapticTypeObject(env)),
139 };
140
141 status = napi_define_class(env, AUDIO_HAPTIC_MANAGER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct,
142 nullptr, sizeof(audioHapticMgrProp) / sizeof(audioHapticMgrProp[0]), audioHapticMgrProp, &ctorObj);
143 if (status == napi_ok) {
144 if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
145 if (napi_set_named_property(env, exports,
146 AUDIO_HAPTIC_MANAGER_NAPI_CLASS_NAME.c_str(), ctorObj) == napi_ok &&
147 napi_define_properties(env, exports,
148 sizeof(staticProp) / sizeof(staticProp[0]), staticProp) == napi_ok) {
149 return exports;
150 }
151 }
152 }
153
154 return nullptr;
155 }
156
Construct(napi_env env,napi_callback_info info)157 napi_value AudioHapticManagerNapi::Construct(napi_env env, napi_callback_info info)
158 {
159 napi_status status;
160 napi_value result = nullptr;
161 napi_value thisVar = nullptr;
162
163 napi_get_undefined(env, &result);
164 status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
165 if (status == napi_ok && thisVar != nullptr) {
166 std::unique_ptr<AudioHapticManagerNapi> obj = std::make_unique<AudioHapticManagerNapi>();
167 if (obj != nullptr) {
168 obj->env_ = env;
169 obj->audioHapticMgrClient_ = AudioHapticManagerFactory::CreateAudioHapticManager();
170 if (obj->audioHapticMgrClient_ == nullptr) {
171 MEDIA_LOGE("Failed to create audioHapticMgrClient_ instance.");
172 return result;
173 }
174
175 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
176 AudioHapticManagerNapi::Destructor, nullptr, nullptr);
177 if (status == napi_ok) {
178 obj.release();
179 return thisVar;
180 } else {
181 MEDIA_LOGE("Failed to wrap the native AudioHapticManager object with JS.");
182 }
183 }
184 }
185
186 return result;
187 }
188
Destructor(napi_env env,void * nativeObject,void * finalizeHint)189 void AudioHapticManagerNapi::Destructor(napi_env env, void *nativeObject, void *finalizeHint)
190 {
191 AudioHapticManagerNapi *audioHapticManagerhelper = reinterpret_cast<AudioHapticManagerNapi*>(nativeObject);
192 if (audioHapticManagerhelper != nullptr) {
193 audioHapticManagerhelper->~AudioHapticManagerNapi();
194 }
195 }
196
GetAudioHapticManager(napi_env env,napi_callback_info info)197 napi_value AudioHapticManagerNapi::GetAudioHapticManager(napi_env env, napi_callback_info info)
198 {
199 napi_status status;
200 napi_value result = nullptr;
201 napi_value ctor;
202
203 status = napi_get_reference_value(env, sConstructor_, &ctor);
204 if (status == napi_ok) {
205 status = napi_new_instance(env, ctor, 0, nullptr, &result);
206 if (status == napi_ok) {
207 return result;
208 } else {
209 MEDIA_LOGE("GetAudioHapticManager: new instance can not be obtained.");
210 }
211 }
212
213 napi_get_undefined(env, &result);
214 return result;
215 }
216
RegisterSource(napi_env env,napi_callback_info info)217 napi_value AudioHapticManagerNapi::RegisterSource(napi_env env, napi_callback_info info)
218 {
219 napi_value result = nullptr;
220 napi_value resource = nullptr;
221 size_t argc = ARGS_TWO;
222 napi_value argv[ARGS_TWO] = {0};
223 char buffer[SIZE];
224 napi_value thisVar = nullptr;
225 size_t res = 0;
226
227 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
228 napi_get_undefined(env, &result);
229 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result, "RegisterSource: napi_get_cb_info fail");
230 if (argc != ARGS_TWO) {
231 MEDIA_LOGE("RegisterSource: requires 2 parameters");
232 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
233 return result;
234 }
235
236 std::unique_ptr<AudioHapticManagerAsyncContext> asyncContext = std::make_unique<AudioHapticManagerAsyncContext>();
237 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
238 CHECK_AND_RETURN_RET_LOG(status == napi_ok && asyncContext->objectInfo != nullptr, result,
239 "RegisterSource: Failed to unwrap object");
240
241 for (size_t i = PARAM0; i < argc; i++) {
242 napi_valuetype valueType = napi_undefined;
243 napi_typeof(env, argv[i], &valueType);
244 if (i == PARAM0 && valueType == napi_string) {
245 napi_get_value_string_utf8(env, argv[i], buffer, SIZE, &res);
246 asyncContext->audioUri = std::string(buffer);
247 } else if (i == PARAM1 && valueType == napi_string) {
248 napi_get_value_string_utf8(env, argv[i], buffer, SIZE, &res);
249 asyncContext->hapticUri = std::string(buffer);
250 } else {
251 MEDIA_LOGE("RegisterSource: the param type mismatch");
252 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID,
253 "incorrect parameter types: The type of audioUri and hapticUri must be string");
254 return result;
255 }
256 }
257 napi_create_promise(env, &asyncContext->deferred, &result);
258
259 napi_create_string_utf8(env, "RegisterSource", NAPI_AUTO_LENGTH, &resource);
260 status = napi_create_async_work(env, nullptr, resource, AsyncRegisterSource,
261 RegisterSourceAsyncCallbackComp, static_cast<void*>(asyncContext.get()), &asyncContext->work);
262 if (status != napi_ok) {
263 MEDIA_LOGE("Failed to get create async work");
264 napi_get_undefined(env, &result);
265 } else {
266 napi_queue_async_work(env, asyncContext->work);
267 asyncContext.release();
268 }
269
270 return result;
271 }
272
AsyncRegisterSource(napi_env env,void * data)273 void AudioHapticManagerNapi::AsyncRegisterSource(napi_env env, void *data)
274 {
275 AudioHapticManagerAsyncContext *context = static_cast<AudioHapticManagerAsyncContext *>(data);
276 if (context->audioUri.empty() || context->hapticUri.empty()) {
277 context->status = ERROR;
278 } else {
279 context->sourceID = context->objectInfo->audioHapticMgrClient_->
280 RegisterSource(context->audioUri, context->hapticUri);
281 context->status = SUCCESS;
282 }
283 }
284
RegisterSourceAsyncCallbackComp(napi_env env,napi_status status,void * data)285 void AudioHapticManagerNapi::RegisterSourceAsyncCallbackComp(napi_env env, napi_status status, void *data)
286 {
287 auto context = static_cast<AudioHapticManagerAsyncContext *>(data);
288 napi_value result[2] = {};
289
290 if (!context->status) {
291 napi_get_undefined(env, &result[PARAM0]);
292 napi_create_int32(env, context->sourceID, &result[PARAM1]);
293 } else {
294 napi_value message = nullptr;
295 napi_create_string_utf8(env, "RegisterSource Error: Operation is not supported or failed",
296 NAPI_AUTO_LENGTH, &message);
297 napi_create_error(env, nullptr, message, &result[PARAM0]);
298 napi_get_undefined(env, &result[PARAM1]);
299 }
300
301 if (context->deferred) {
302 if (!context->status) {
303 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
304 } else {
305 napi_reject_deferred(env, context->deferred, result[PARAM0]);
306 }
307 }
308 napi_delete_async_work(env, context->work);
309
310 delete context;
311 context = nullptr;
312 }
313
UnregisterSource(napi_env env,napi_callback_info info)314 napi_value AudioHapticManagerNapi::UnregisterSource(napi_env env, napi_callback_info info)
315 {
316 napi_value result = nullptr;
317 napi_value resource = nullptr;
318 size_t argc = ARGS_ONE;
319 napi_value argv[ARGS_ONE] = {0};
320 napi_value thisVar = nullptr;
321
322 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
323 napi_get_undefined(env, &result);
324 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
325 "UnregisterSource: Failed to retrieve details about the callback");
326 if (argc != ARGS_ONE) {
327 MEDIA_LOGE("UnregisterSource: requires 1 parameter");
328 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
329 return result;
330 }
331
332 std::unique_ptr<AudioHapticManagerAsyncContext> asyncContext = std::make_unique<AudioHapticManagerAsyncContext>();
333 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
334 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
335 napi_valuetype valueType = napi_undefined;
336 napi_typeof(env, argv[PARAM0], &valueType);
337 if (valueType == napi_number) {
338 napi_get_value_int32(env, argv[PARAM0], &asyncContext->sourceID);
339 } else {
340 MEDIA_LOGE("UnregisterSource: the param type mismatch");
341 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID,
342 "incorrect parameter types: The type of id must be number");
343 return result;
344 }
345 napi_create_promise(env, &asyncContext->deferred, &result);
346
347 napi_create_string_utf8(env, "UnregisterSource", NAPI_AUTO_LENGTH, &resource);
348 status = napi_create_async_work(env, nullptr, resource,
349 [](napi_env env, void *data) {
350 AudioHapticManagerAsyncContext *context = static_cast<AudioHapticManagerAsyncContext*>(data);
351 context->status = context->objectInfo->audioHapticMgrClient_->UnregisterSource(context->sourceID);
352 },
353 UnregisterSourceAsyncCallbackComp, static_cast<void*>(asyncContext.get()), &asyncContext->work);
354 if (status != napi_ok) {
355 MEDIA_LOGE("GetRingtoneUri: Failed to get create async work");
356 napi_get_undefined(env, &result);
357 } else {
358 napi_queue_async_work(env, asyncContext->work);
359 asyncContext.release();
360 }
361 }
362
363 return result;
364 }
365
UnregisterSourceAsyncCallbackComp(napi_env env,napi_status status,void * data)366 void AudioHapticManagerNapi::UnregisterSourceAsyncCallbackComp(napi_env env, napi_status status, void *data)
367 {
368 auto context = static_cast<AudioHapticManagerAsyncContext *>(data);
369 napi_value result[2] = {};
370
371 napi_get_undefined(env, &result[PARAM1]);
372 if (!context->status) {
373 napi_get_undefined(env, &result[PARAM0]);
374 } else {
375 napi_value message = nullptr;
376 napi_create_string_utf8(env, "UnregisterSource Error: Operation is not supported or failed",
377 NAPI_AUTO_LENGTH, &message);
378 napi_create_error(env, nullptr, message, &result[PARAM0]);
379 }
380
381 if (context->deferred) {
382 if (!context->status) {
383 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
384 } else {
385 napi_reject_deferred(env, context->deferred, result[PARAM0]);
386 }
387 }
388 napi_delete_async_work(env, context->work);
389
390 delete context;
391 context = nullptr;
392 }
393
SetAudioLatencyMode(napi_env env,napi_callback_info info)394 napi_value AudioHapticManagerNapi::SetAudioLatencyMode(napi_env env, napi_callback_info info)
395 {
396 napi_value result = nullptr;
397
398 size_t argc = ARGS_TWO;
399 napi_value argv[ARGS_TWO] = {0};
400 napi_value thisVar = nullptr;
401 void *data;
402 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
403 if (argc != ARGS_TWO) {
404 MEDIA_LOGE("SetAudioLatencyMode: requires 2 parameters");
405 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID);
406 return result;
407 }
408
409 void *native = nullptr;
410 napi_status status = napi_unwrap(env, thisVar, &native);
411 auto *audioHapticManagerNapi = reinterpret_cast<AudioHapticManagerNapi *>(native);
412 if (status != napi_ok || audioHapticManagerNapi == nullptr) {
413 MEDIA_LOGE("SetAudioLatencyMode: unwrap failure!");
414 return result;
415 }
416
417 napi_valuetype valueType = napi_undefined;
418 napi_typeof(env, argv[PARAM0], &valueType);
419 if (valueType != napi_number) {
420 MEDIA_LOGE("SetAudioLatencyMode: the param type mismatch");
421 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID);
422 return result;
423 }
424 int32_t sourceID = 0;
425 napi_get_value_int32(env, argv[PARAM0], &sourceID);
426
427 napi_typeof(env, argv[PARAM1], &valueType);
428 if (valueType != napi_number) {
429 MEDIA_LOGE("SetAudioLatencyMode: the param type mismatch");
430 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID);
431 return result;
432 }
433 int32_t latencyMode = 0;
434 napi_get_value_int32(env, argv[PARAM1], &latencyMode);
435 if (!IsLegalAudioLatencyMode (latencyMode)) {
436 MEDIA_LOGE("SetAudioLatencyMode: the value of latencyMode is invalid");
437 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID);
438 return result;
439 }
440
441 int32_t setResult = audioHapticManagerNapi->audioHapticMgrClient_->
442 SetAudioLatencyMode(sourceID, static_cast<AudioLatencyMode>(latencyMode));
443 if (setResult != SUCCESS) {
444 MEDIA_LOGE("SetAudioLatencyMode: Failed to set audio latency mode");
445 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_OPERATE_NOT_ALLOWED);
446 }
447 return result;
448 }
449
IsLegalAudioLatencyMode(int32_t latencyMode)450 bool AudioHapticManagerNapi::IsLegalAudioLatencyMode(int32_t latencyMode)
451 {
452 switch (latencyMode) {
453 case AUDIO_LATENCY_MODE_NORMAL:
454 case AUDIO_LATENCY_MODE_FAST:
455 return true;
456 default:
457 break;
458 }
459 MEDIA_LOGE("IsLegalAudioLatencyMode: latencyMode %{public}d is invalid", latencyMode);
460 return false;
461 }
462
SetStreamUsage(napi_env env,napi_callback_info info)463 napi_value AudioHapticManagerNapi::SetStreamUsage(napi_env env, napi_callback_info info)
464 {
465 napi_value result = nullptr;
466
467 size_t argc = ARGS_TWO;
468 napi_value argv[ARGS_TWO] = {0};
469 napi_value thisVar = nullptr;
470 void *data;
471 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
472 if (argc != ARGS_TWO) {
473 MEDIA_LOGE("SetStreamUsage: requires 2 parameters");
474 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
475 return result;
476 }
477
478 void *native = nullptr;
479 napi_status status = napi_unwrap(env, thisVar, &native);
480 auto *audioHapticManagerNapi = reinterpret_cast<AudioHapticManagerNapi *>(native);
481 if (status != napi_ok || audioHapticManagerNapi == nullptr) {
482 MEDIA_LOGE("SetStreamUsage: unwrap failure!");
483 return result;
484 }
485
486 napi_valuetype valueType = napi_undefined;
487 napi_typeof(env, argv[PARAM0], &valueType);
488 if (valueType != napi_number) {
489 MEDIA_LOGE("SetStreamUsage: the param type mismatch");
490 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID, "the type of id must be number");
491 return result;
492 }
493 int32_t sourceID = 0;
494 napi_get_value_int32(env, argv[PARAM0], &sourceID);
495
496 napi_typeof(env, argv[PARAM1], &valueType);
497 if (valueType != napi_number) {
498 MEDIA_LOGE("SetStreamUsage: the param type mismatch");
499 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID, "the type of usage must be number");
500 return result;
501 }
502 int32_t streamUsage = 0;
503 napi_get_value_int32(env, argv[PARAM1], &streamUsage);
504 if (!IsLegalAudioStreamUsage (streamUsage)) {
505 MEDIA_LOGE("SetStreamUsage: the value of streamUsage is invalid");
506 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID,
507 "the param of usage must be enum audio.StreamUsage");
508 return result;
509 }
510
511 int32_t setResult = audioHapticManagerNapi->audioHapticMgrClient_->
512 SetStreamUsage(sourceID, static_cast<AudioStandard::StreamUsage>(streamUsage));
513 if (setResult != SUCCESS) {
514 MEDIA_LOGE("SetStreamUsage: Failed to set audio stream usage");
515 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_OPERATE_NOT_ALLOWED);
516 }
517 return result;
518 }
519
IsLegalAudioStreamUsage(int32_t streamUsage)520 bool AudioHapticManagerNapi::IsLegalAudioStreamUsage(int32_t streamUsage)
521 {
522 switch (streamUsage) {
523 case AudioStandard::STREAM_USAGE_MUSIC:
524 case AudioStandard::STREAM_USAGE_VOICE_COMMUNICATION:
525 case AudioStandard::STREAM_USAGE_VOICE_ASSISTANT:
526 case AudioStandard::STREAM_USAGE_ALARM:
527 case AudioStandard::STREAM_USAGE_VOICE_MESSAGE:
528 case AudioStandard::STREAM_USAGE_RINGTONE:
529 case AudioStandard::STREAM_USAGE_NOTIFICATION:
530 case AudioStandard::STREAM_USAGE_ACCESSIBILITY:
531 case AudioStandard::STREAM_USAGE_SYSTEM:
532 case AudioStandard::STREAM_USAGE_MOVIE:
533 case AudioStandard::STREAM_USAGE_GAME:
534 case AudioStandard::STREAM_USAGE_AUDIOBOOK:
535 case AudioStandard::STREAM_USAGE_NAVIGATION:
536 case AudioStandard::STREAM_USAGE_DTMF:
537 case AudioStandard::STREAM_USAGE_ENFORCED_TONE:
538 return true;
539 default:
540 break;
541 }
542 MEDIA_LOGE("IsLegalAudioStreamUsage: streamUsage %{public}d is invalid", streamUsage);
543 return false;
544 }
545
CreatePlayer(napi_env env,napi_callback_info info)546 napi_value AudioHapticManagerNapi::CreatePlayer(napi_env env, napi_callback_info info)
547 {
548 napi_value result = nullptr;
549 napi_value property = nullptr;
550 napi_value resource = nullptr;
551 size_t argc = ARGS_TWO;
552 napi_value argv[ARGS_TWO] = {0};
553 napi_value thisVar = nullptr;
554
555 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
556 napi_get_undefined(env, &result);
557 CHECK_AND_RETURN_RET_LOG((status == napi_ok && thisVar != nullptr), result, "napi_get_cb_info failed");
558 if (argc != ARGS_ONE && argc != ARGS_TWO) {
559 MEDIA_LOGE("CreatePlayer: requires 1 parameter or 2 parameters");
560 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
561 return result;
562 }
563
564 std::unique_ptr<AudioHapticManagerAsyncContext> asyncContext = std::make_unique<AudioHapticManagerAsyncContext>();
565 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
566 CHECK_AND_RETURN_RET_LOG(status == napi_ok && asyncContext->objectInfo != nullptr, result, "objectInfo invalid");
567
568 for (size_t i = PARAM0; i < argc; i++) {
569 napi_valuetype valueType = napi_undefined;
570 napi_typeof(env, argv[i], &valueType);
571 if (i == PARAM0 && valueType == napi_number) {
572 napi_get_value_int32(env, argv[i], &asyncContext->sourceID);
573 } else if (i == PARAM1 && valueType == napi_object) {
574 if (napi_get_named_property(env, argv[PARAM1], "muteAudio", &property) == napi_ok) {
575 napi_get_value_bool(env, property, &(asyncContext->playerOptions.muteAudio));
576 }
577 if (napi_get_named_property(env, argv[PARAM1], "muteHaptics", &property) == napi_ok) {
578 napi_get_value_bool(env, property, &(asyncContext->playerOptions.muteHaptics));
579 }
580 } else {
581 MEDIA_LOGE("CreatePlayer: the param type mismatch");
582 AudioHapticCommonNapi::ThrowError(env, NAPI_ERR_INPUT_INVALID,
583 "incorrect parameter types: The type of id must be number; The type of options must be object");
584 return result;
585 }
586 }
587 napi_create_promise(env, &asyncContext->deferred, &result);
588
589 napi_create_string_utf8(env, "CreatePlayer", NAPI_AUTO_LENGTH, &resource);
590 status = napi_create_async_work(env, nullptr, resource, AsyncCreatePlayer,
591 CreatePlayerAsyncCallbackComp, static_cast<void*>(asyncContext.get()), &asyncContext->work);
592 if (status != napi_ok) {
593 MEDIA_LOGE("CreatePlayer: Failed to get create async work");
594 napi_get_undefined(env, &result);
595 } else {
596 napi_queue_async_work(env, asyncContext->work);
597 asyncContext.release();
598 }
599
600 return result;
601 }
602
AsyncCreatePlayer(napi_env env,void * data)603 void AudioHapticManagerNapi::AsyncCreatePlayer(napi_env env, void *data)
604 {
605 AudioHapticManagerAsyncContext *context = static_cast<AudioHapticManagerAsyncContext *>(data);
606 std::shared_ptr<AudioHapticPlayer> audioHapticPlayer =
607 context->objectInfo->audioHapticMgrClient_->CreatePlayer(context->sourceID, context->playerOptions);
608 if (audioHapticPlayer != nullptr) {
609 int32_t result = audioHapticPlayer->Prepare();
610 if (result == MSERR_OK) {
611 context->audioHapticPlayer = audioHapticPlayer;
612 context->status = SUCCESS;
613 return;
614 }
615 // Fail to prepare the audio haptic player. Throw err.
616 if (result == MSERR_OPEN_FILE_FAILED) {
617 context->errCode = NAPI_ERR_IO_ERROR;
618 } else if (result == MSERR_UNSUPPORT_FILE) {
619 context->errCode = NAPI_ERR_UNSUPPORTED_FORMAT;
620 } else {
621 context->errCode = NAPI_ERR_OPERATE_NOT_ALLOWED;
622 }
623 } else {
624 context->errCode = NAPI_ERR_OPERATE_NOT_ALLOWED;
625 }
626 context->audioHapticPlayer = nullptr;
627 context->status = ERROR;
628 context->errMessage = AudioHapticCommonNapi::GetMessageByCode(context->errCode);
629 }
630
CreatePlayerAsyncCallbackComp(napi_env env,napi_status status,void * data)631 void AudioHapticManagerNapi::CreatePlayerAsyncCallbackComp(napi_env env, napi_status status, void *data)
632 {
633 auto context = static_cast<AudioHapticManagerAsyncContext *>(data);
634 napi_value result[2] = {};
635 napi_value playerResult = nullptr;
636
637 if (context->audioHapticPlayer != nullptr) {
638 playerResult = AudioHapticPlayerNapi::CreatePlayerInstance(env, context->audioHapticPlayer);
639 if (playerResult == nullptr) {
640 napi_value message = nullptr;
641 napi_create_string_utf8(env, "CreatePlayer Error: Operation is not supported or failed",
642 NAPI_AUTO_LENGTH, &message);
643 napi_create_error(env, nullptr, message, &result[PARAM0]);
644 napi_get_undefined(env, &result[PARAM1]);
645 } else {
646 napi_get_undefined(env, &result[PARAM0]);
647 result[PARAM1] = playerResult;
648 }
649 } else {
650 MEDIA_LOGE("CreatePlayer: Failed to create audio haptic player!");
651 napi_value message = nullptr;
652 napi_value code = nullptr;
653 napi_create_string_utf8(env, context->errMessage.c_str(), NAPI_AUTO_LENGTH, &message);
654 napi_create_error(env, nullptr, message, &result[PARAM0]);
655 napi_create_int32(env, context->errCode, &code);
656 napi_set_named_property(env, result[PARAM0], "code", code);
657 napi_get_undefined(env, &result[PARAM1]);
658 }
659
660 if (context->deferred) {
661 if (context->status == SUCCESS) {
662 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
663 } else {
664 napi_reject_deferred(env, context->deferred, result[PARAM0]);
665 }
666 }
667 napi_delete_async_work(env, context->work);
668
669 delete context;
670 context = nullptr;
671 }
672
Init(napi_env env,napi_value exports)673 static napi_value Init(napi_env env, napi_value exports)
674 {
675 AudioHapticManagerNapi::Init(env, exports);
676 AudioHapticPlayerNapi::Init(env, exports);
677 AudioHapticPlayerOptionsNapi::Init(env, exports);
678
679 return exports;
680 }
681
682 /*
683 * module define
684 */
685 static napi_module g_module = {
686 .nm_version = 1,
687 .nm_flags = 0,
688 .nm_filename = nullptr,
689 .nm_register_func = Init,
690 .nm_modname = "multimedia.audioHaptic",
691 .nm_priv = (reinterpret_cast<void*>(0)),
692 .reserved = {0}
693 };
694
695 /*
696 * module register
697 */
RegisterModule(void)698 extern "C" __attribute__((constructor)) void RegisterModule(void)
699 {
700 napi_module_register(&g_module);
701 }
702 } // namespace Media
703 } // namespace OHOS