• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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