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 "common_napi.h"
17 #include <climits>
18 #include "avcodec_list.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21
22 namespace {
23 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "CommonNapi"};
24 }
25
26 namespace OHOS {
27 namespace Media {
GetStringArgument(napi_env env,napi_value value,size_t maxLength)28 std::string CommonNapi::GetStringArgument(napi_env env, napi_value value, size_t maxLength)
29 {
30 std::string strValue = "";
31 size_t bufLength = 0;
32 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufLength);
33 if (status == napi_ok && bufLength > 0 && bufLength < maxLength) {
34 char *buffer = static_cast<char *>(malloc((bufLength + 1) * sizeof(char)));
35 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, strValue, "no memory");
36 status = napi_get_value_string_utf8(env, value, buffer, bufLength + 1, &bufLength);
37 if (status == napi_ok) {
38 MEDIA_LOGD("argument = %{public}s", buffer);
39 strValue = buffer;
40 }
41 free(buffer);
42 buffer = nullptr;
43 }
44 return strValue;
45 }
46
CheckValueType(napi_env env,napi_value arg,napi_valuetype type)47 bool CommonNapi::CheckValueType(napi_env env, napi_value arg, napi_valuetype type)
48 {
49 napi_valuetype valueType = napi_undefined;
50 if (arg != nullptr && napi_typeof(env, arg, &valueType) == napi_ok && valueType == type) {
51 return true;
52 }
53 return false;
54 }
55
CheckhasNamedProperty(napi_env env,napi_value arg,std::string type)56 bool CommonNapi::CheckhasNamedProperty(napi_env env, napi_value arg, std::string type)
57 {
58 bool exist = false;
59 napi_status napiStatus = napi_has_named_property(env, arg, type.c_str(), &exist);
60 return exist && (napiStatus == napi_ok);
61 }
62
GetPropertyInt32(napi_env env,napi_value configObj,const std::string & type,int32_t & result)63 bool CommonNapi::GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result)
64 {
65 napi_value item = nullptr;
66 bool exist = false;
67 napi_status napiStatus = napi_has_named_property(env, configObj, type.c_str(), &exist);
68 CHECK_AND_RETURN_RET_LOG(napiStatus == napi_ok && exist, false, "can not find %{public}s property", type.c_str());
69 CHECK_AND_RETURN_RET_LOG(napi_get_named_property(env, configObj, type.c_str(), &item) == napi_ok, false,
70 "get %{public}s property fail", type.c_str());
71 CHECK_AND_RETURN_RET_LOG(napi_get_value_int32(env, item, &result) == napi_ok, false,
72 "get %{public}s property value fail", type.c_str());
73 return true;
74 }
75
GetPropertyUint32(napi_env env,napi_value configObj,const std::string & type,uint32_t & result)76 bool CommonNapi::GetPropertyUint32(napi_env env, napi_value configObj, const std::string &type, uint32_t &result)
77 {
78 napi_value item = nullptr;
79 bool exist = false;
80 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
81 CHECK_AND_RETURN_RET_LOG(status == napi_ok && exist, false, "can not find %{public}s property", type.c_str());
82 CHECK_AND_RETURN_RET_LOG(napi_get_named_property(env, configObj, type.c_str(), &item) == napi_ok, false,
83 "get %{public}s property fail", type.c_str());
84
85 CHECK_AND_RETURN_RET_LOG(napi_get_value_uint32(env, item, &result) == napi_ok, false,
86 "get %{public}s property value fail", type.c_str());
87 return true;
88 }
89
GetPropertyInt64(napi_env env,napi_value configObj,const std::string & type,int64_t & result)90 bool CommonNapi::GetPropertyInt64(napi_env env, napi_value configObj, const std::string &type, int64_t &result)
91 {
92 napi_value item = nullptr;
93 bool exist = false;
94 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
95 if (status != napi_ok || !exist) {
96 MEDIA_LOGE("can not find %{public}s property", type.c_str());
97 return false;
98 }
99
100 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
101 MEDIA_LOGE("get %{public}s property fail", type.c_str());
102 return false;
103 }
104
105 if (napi_get_value_int64(env, item, &result) != napi_ok) {
106 MEDIA_LOGE("get %{public}s property value fail", type.c_str());
107 return false;
108 }
109 return true;
110 }
111
GetPropertyDouble(napi_env env,napi_value configObj,const std::string & type,double & result)112 bool CommonNapi::GetPropertyDouble(napi_env env, napi_value configObj, const std::string &type, double &result)
113 {
114 napi_value item = nullptr;
115 bool exist = false;
116 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
117 if (status != napi_ok || !exist) {
118 MEDIA_LOGE("can not find %{public}s property", type.c_str());
119 return false;
120 }
121
122 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
123 MEDIA_LOGE("get %{public}s property fail", type.c_str());
124 return false;
125 }
126
127 if (napi_get_value_double(env, item, &result) != napi_ok) {
128 MEDIA_LOGE("get %{public}s property value fail", type.c_str());
129 return false;
130 }
131 return true;
132 }
133
GetPropertyString(napi_env env,napi_value configObj,const std::string & type)134 std::string CommonNapi::GetPropertyString(napi_env env, napi_value configObj, const std::string &type)
135 {
136 std::string invalid = "";
137 bool exist = false;
138 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
139 if (status != napi_ok || !exist) {
140 MEDIA_LOGE("can not find %{public}s property", type.c_str());
141 return invalid;
142 }
143
144 napi_value item = nullptr;
145 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
146 MEDIA_LOGE("get %{public}s property fail", type.c_str());
147 return invalid;
148 }
149
150 return GetStringArgument(env, item);
151 }
152
GetPropertyRecord(napi_env env,napi_value configObj,Meta & meta,std::string type)153 napi_status CommonNapi::GetPropertyRecord(napi_env env, napi_value configObj, Meta &meta, std::string type)
154 {
155 bool exist = false;
156 napi_value in = nullptr;
157 napi_valuetype valueType = napi_undefined;
158 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
159 if (status != napi_ok || !exist) {
160 MEDIA_LOGE("can not find %{public}s property", type.c_str());
161 return napi_invalid_arg;
162 }
163 if (napi_get_named_property(env, configObj, type.c_str(), &in) != napi_ok) {
164 MEDIA_LOGE("get %{public}s property fail", type.c_str());
165 return napi_invalid_arg;
166 }
167 status = napi_typeof(env, in, &valueType);
168 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get valueType failed");
169 CHECK_AND_RETURN_RET_LOG(valueType != napi_undefined, napi_ok, "PropertyRecord undefined");
170 CHECK_AND_RETURN_RET_LOG(valueType == napi_object, napi_invalid_arg, "invalid arguments");
171
172 napi_value dataList = nullptr;
173 uint32_t count = 0;
174 status = napi_get_property_names(env, in, &dataList);
175 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get property names failed");
176 status = napi_get_array_length(env, dataList, &count);
177 CHECK_AND_RETURN_RET_LOG(status == napi_ok && count <= MAX_COUNT,
178 napi_invalid_arg, "get length failed or more than 500");
179
180 napi_value jsKey = nullptr;
181 napi_value jsValue = nullptr;
182 for (uint32_t i = 0; i < count; i++) {
183 status = napi_get_element(env, dataList, i, &jsKey);
184 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get element Key failed");
185 status = napi_typeof(env, jsKey, &valueType);
186 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get valueType failed");
187 CHECK_AND_RETURN_RET_LOG(valueType == napi_string, napi_invalid_arg, "key not supported type");
188 std::string strKey = GetStringArgument(env, jsKey, CUSTOM_MAX_LENGTH);
189 CHECK_AND_RETURN_RET_LOG(strKey != "", napi_invalid_arg, "key not supported");
190
191 status = napi_get_named_property(env, in, strKey.c_str(), &jsValue);
192 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get property value failed");
193 status = napi_typeof(env, jsValue, &valueType);
194 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get valueType failed");
195
196 CHECK_AND_RETURN_RET_LOG(valueType == napi_string, napi_invalid_arg, "value not supported type");
197 std::string strValue = GetStringArgument(env, jsValue, CUSTOM_MAX_LENGTH);
198 CHECK_AND_RETURN_RET_LOG(!strValue.empty(), napi_invalid_arg, "get value failed");
199 meta.SetData(strKey, strValue);
200 }
201 return napi_ok;
202 }
203
GetFdArgument(napi_env env,napi_value value,AVFileDescriptor & rawFd)204 bool CommonNapi::GetFdArgument(napi_env env, napi_value value, AVFileDescriptor &rawFd)
205 {
206 CHECK_AND_RETURN_RET(GetPropertyInt32(env, value, "fd", rawFd.fd) == true, false);
207
208 if (!GetPropertyInt64(env, value, "offset", rawFd.offset)) {
209 rawFd.offset = 0; // use default value
210 }
211
212 if (!GetPropertyInt64(env, value, "length", rawFd.length)) {
213 rawFd.length = -1; // -1 means use default value
214 }
215
216 MEDIA_LOGD("get fd argument, fd = %{public}d, offset = %{public}" PRIi64 ", size = %{public}" PRIi64 "",
217 rawFd.fd, rawFd.offset, rawFd.length);
218
219 return true;
220 }
221
GetPropertyMap(napi_env env,napi_value value,std::map<std::string,std::string> & map)222 bool CommonNapi::GetPropertyMap(napi_env env, napi_value value, std::map<std::string, std::string>& map)
223 {
224 napi_value jsProNameList = nullptr;
225 uint32_t jsProCount = 0;
226 napi_status status = napi_get_property_names(env, value, &jsProNameList);
227 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "get property name failed");
228 status = napi_get_array_length(env, jsProNameList, &jsProCount);
229 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "get subKeys length failed");
230
231 napi_value jsProName = nullptr;
232 napi_value jsProValue = nullptr;
233 for (uint32_t i = 0; i < jsProCount; i++) {
234 status = napi_get_element(env, jsProNameList, i, &jsProName);
235 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "get sub key failed");
236 std::string strProName = GetStringArgument(env, jsProName);
237
238 status = napi_get_named_property(env, value, strProName.c_str(), &jsProValue);
239 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "get sub value failed");
240 std::string strProValue = GetStringArgument(env, jsProValue);
241
242 map.emplace(strProName, strProValue);
243 }
244
245 return true;
246 }
247
GetPlayStrategy(napi_env env,napi_value value,AVPlayStrategyTmp & playStrategy)248 bool CommonNapi::GetPlayStrategy(napi_env env, napi_value value, AVPlayStrategyTmp &playStrategy)
249 {
250 if (!GetPropertyUint32(env, value, "preferredWidth", playStrategy.preferredWidth)) {
251 playStrategy.preferredWidth = 0; // use default value
252 }
253 if (!GetPropertyUint32(env, value, "preferredHeight", playStrategy.preferredHeight)) {
254 playStrategy.preferredHeight = 0; // use default value
255 }
256 if (!GetPropertyUint32(env, value, "preferredBufferDuration", playStrategy.preferredBufferDuration)) {
257 playStrategy.preferredBufferDuration = 0; // use default value
258 }
259 if (!GetPropertyBool(env, value, "preferredHdr", playStrategy.preferredHdr)) {
260 playStrategy.preferredHdr = 0; // use default value
261 }
262 if (!GetPropertyInt32(env, value, "mutedMediaType", playStrategy.mutedMediaType)) {
263 playStrategy.mutedMediaType = MediaType::MEDIA_TYPE_MAX_COUNT; // use default value
264 }
265 playStrategy.preferredAudioLanguage = GetPropertyString(env, value, "preferredAudioLanguage");
266 playStrategy.preferredSubtitleLanguage = GetPropertyString(env, value, "preferredSubtitleLanguage");
267 return true;
268 }
269
FillErrorArgs(napi_env env,int32_t errCode,const napi_value & args)270 napi_status CommonNapi::FillErrorArgs(napi_env env, int32_t errCode, const napi_value &args)
271 {
272 napi_value codeStr = nullptr;
273 napi_status status = napi_create_string_utf8(env, "code", NAPI_AUTO_LENGTH, &codeStr);
274 CHECK_AND_RETURN_RET_LOG(status == napi_ok && codeStr != nullptr, napi_invalid_arg, "create code str fail");
275
276 napi_value errCodeVal = nullptr;
277 int32_t errCodeInt = errCode;
278 status = napi_create_int32(env, errCodeInt, &errCodeVal);
279 CHECK_AND_RETURN_RET_LOG(status == napi_ok && errCodeVal != nullptr, napi_invalid_arg,
280 "create error code number val fail");
281
282 status = napi_set_property(env, args, codeStr, errCodeVal);
283 CHECK_AND_RETURN_RET_LOG(status == napi_ok, napi_invalid_arg, "set error code property fail");
284
285 napi_value nameStr = nullptr;
286 status = napi_create_string_utf8(env, "name", NAPI_AUTO_LENGTH, &nameStr);
287 CHECK_AND_RETURN_RET_LOG(status == napi_ok && nameStr != nullptr, napi_invalid_arg, "create name str fail");
288
289 napi_value errNameVal = nullptr;
290 status = napi_create_string_utf8(env, "BusinessError", NAPI_AUTO_LENGTH, &errNameVal);
291 CHECK_AND_RETURN_RET_LOG(status == napi_ok && errNameVal != nullptr, napi_invalid_arg,
292 "create BusinessError str fail");
293
294 status = napi_set_property(env, args, nameStr, errNameVal);
295 CHECK_AND_RETURN_RET_LOG(status == napi_ok, napi_invalid_arg, "set error name property fail");
296 return napi_ok;
297 }
298
CreateError(napi_env env,int32_t errCode,const std::string & errMsg,napi_value & errVal)299 napi_status CommonNapi::CreateError(napi_env env, int32_t errCode, const std::string &errMsg, napi_value &errVal)
300 {
301 napi_get_undefined(env, &errVal);
302
303 napi_value msgValStr = nullptr;
304 napi_status nstatus = napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &msgValStr);
305 if (nstatus != napi_ok || msgValStr == nullptr) {
306 MEDIA_LOGE("create error message str fail");
307 return napi_invalid_arg;
308 }
309
310 nstatus = napi_create_error(env, nullptr, msgValStr, &errVal);
311 if (nstatus != napi_ok || errVal == nullptr) {
312 MEDIA_LOGE("create error fail");
313 return napi_invalid_arg;
314 }
315
316 napi_value codeStr = nullptr;
317 nstatus = napi_create_string_utf8(env, "code", NAPI_AUTO_LENGTH, &codeStr);
318 if (nstatus != napi_ok || codeStr == nullptr) {
319 MEDIA_LOGE("create code str fail");
320 return napi_invalid_arg;
321 }
322
323 napi_value errCodeVal = nullptr;
324 nstatus = napi_create_int32(env, errCode, &errCodeVal);
325 if (nstatus != napi_ok || errCodeVal == nullptr) {
326 MEDIA_LOGE("create error code number val fail");
327 return napi_invalid_arg;
328 }
329
330 nstatus = napi_set_property(env, errVal, codeStr, errCodeVal);
331 if (nstatus != napi_ok) {
332 MEDIA_LOGE("set error code property fail");
333 return napi_invalid_arg;
334 }
335
336 napi_value nameStr = nullptr;
337 nstatus = napi_create_string_utf8(env, "name", NAPI_AUTO_LENGTH, &nameStr);
338 if (nstatus != napi_ok || nameStr == nullptr) {
339 MEDIA_LOGE("create name str fail");
340 return napi_invalid_arg;
341 }
342
343 napi_value errNameVal = nullptr;
344 nstatus = napi_create_string_utf8(env, "BusinessError", NAPI_AUTO_LENGTH, &errNameVal);
345 if (nstatus != napi_ok || errNameVal == nullptr) {
346 MEDIA_LOGE("create BusinessError str fail");
347 return napi_invalid_arg;
348 }
349
350 nstatus = napi_set_property(env, errVal, nameStr, errNameVal);
351 if (nstatus != napi_ok) {
352 MEDIA_LOGE("set error name property fail");
353 return napi_invalid_arg;
354 }
355
356 return napi_ok;
357 }
358
CreateReference(napi_env env,napi_value arg)359 napi_ref CommonNapi::CreateReference(napi_env env, napi_value arg)
360 {
361 napi_ref ref = nullptr;
362 napi_valuetype valueType = napi_undefined;
363 if (arg != nullptr && napi_typeof(env, arg, &valueType) == napi_ok && valueType == napi_function) {
364 MEDIA_LOGD("napi_create_reference");
365 napi_create_reference(env, arg, 1, &ref);
366 }
367 return ref;
368 }
369
CreatePromise(napi_env env,napi_ref ref,napi_value & result)370 napi_deferred CommonNapi::CreatePromise(napi_env env, napi_ref ref, napi_value &result)
371 {
372 napi_deferred deferred = nullptr;
373 if (ref == nullptr) {
374 MEDIA_LOGD("napi_create_promise");
375 napi_create_promise(env, &deferred, &result);
376 }
377 return deferred;
378 }
379
SetPropertyByValueType(napi_env env,napi_value & obj,std::shared_ptr<Meta> & meta,std::string key)380 bool CommonNapi::SetPropertyByValueType(napi_env env, napi_value &obj, std::shared_ptr<Meta> &meta, std::string key)
381 {
382 CHECK_AND_RETURN_RET(obj != nullptr && meta != nullptr, false);
383 CHECK_AND_RETURN_RET(meta->Find(key) != meta->end(), false);
384
385 bool ret = true;
386 AnyValueType type = meta->GetValueType(key);
387 if (type == AnyValueType::STRING) {
388 std::string sValue;
389 ret = meta->GetData(key, sValue);
390 CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
391 ret = CommonNapi::SetPropertyString(env, obj, key, sValue);
392 CHECK_AND_RETURN_RET_LOG(ret, ret, "SetPropertyString failed, key %{public}s", key.c_str());
393 } else if (type == AnyValueType::INT32_T) {
394 int32_t value;
395 ret = meta->GetData(key, value);
396 CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
397 ret = CommonNapi::SetPropertyInt32(env, obj, key, value);
398 CHECK_AND_RETURN_RET_LOG(ret, ret, "SetPropertyString failed, key %{public}s", key.c_str());
399 } else if (type == AnyValueType::FLOAT) {
400 float dValue;
401 ret = meta->GetData(key, dValue);
402 CHECK_AND_RETURN_RET_LOG(ret, ret, "GetData failed, key %{public}s", key.c_str());
403 ret = CommonNapi::SetPropertyDouble(env, obj, key, dValue);
404 CHECK_AND_RETURN_RET_LOG(ret, ret, "SetPropertyString failed, key %{public}s", key.c_str());
405 } else {
406 MEDIA_LOGE("not supported value type");
407 }
408 return true;
409 }
410
AddRangeProperty(napi_env env,napi_value obj,const std::string & name,int32_t min,int32_t max)411 bool CommonNapi::AddRangeProperty(napi_env env, napi_value obj, const std::string &name, int32_t min, int32_t max)
412 {
413 CHECK_AND_RETURN_RET(obj != nullptr, false);
414
415 napi_value range = nullptr;
416 napi_status status = napi_create_object(env, &range);
417 CHECK_AND_RETURN_RET(status == napi_ok, false);
418
419 CHECK_AND_RETURN_RET(SetPropertyInt32(env, range, "min", min) == true, false);
420 CHECK_AND_RETURN_RET(SetPropertyInt32(env, range, "max", max) == true, false);
421
422 napi_value nameStr = nullptr;
423 status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &nameStr);
424 CHECK_AND_RETURN_RET(status == napi_ok, false);
425
426 status = napi_set_property(env, obj, nameStr, range);
427 CHECK_AND_RETURN_RET(status == napi_ok, false);
428
429 return true;
430 }
431
AddArrayProperty(napi_env env,napi_value obj,const std::string & name,const std::vector<int32_t> & vec)432 bool CommonNapi::AddArrayProperty(napi_env env, napi_value obj, const std::string &name,
433 const std::vector<int32_t> &vec)
434 {
435 CHECK_AND_RETURN_RET(obj != nullptr, false);
436
437 napi_value array = nullptr;
438 napi_status status = napi_create_array_with_length(env, vec.size(), &array);
439 CHECK_AND_RETURN_RET(status == napi_ok, false);
440
441 for (uint32_t i = 0; i < vec.size(); i++) {
442 napi_value number = nullptr;
443 (void)napi_create_int32(env, vec.at(i), &number);
444 (void)napi_set_element(env, array, i, number);
445 }
446
447 napi_value nameStr = nullptr;
448 status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &nameStr);
449 CHECK_AND_RETURN_RET(status == napi_ok, false);
450
451 status = napi_set_property(env, obj, nameStr, array);
452 CHECK_AND_RETURN_RET(status == napi_ok, false);
453
454 return true;
455 }
456
AddArrayInt(napi_env env,napi_value & array,const std::vector<int32_t> & vec)457 bool CommonNapi::AddArrayInt(napi_env env, napi_value &array, const std::vector<int32_t> &vec)
458 {
459 if (vec.size() == 0) {
460 return false;
461 }
462
463 napi_status status = napi_create_array_with_length(env, vec.size(), &array);
464 CHECK_AND_RETURN_RET(status == napi_ok, false);
465
466 for (uint32_t i = 0; i < vec.size(); i++) {
467 napi_value number = nullptr;
468 (void)napi_create_int32(env, vec.at(i), &number);
469 (void)napi_set_element(env, array, i, number);
470 }
471
472 return true;
473 }
474
SetPropertyInt32(napi_env env,napi_value & obj,const std::string & key,int32_t value)475 bool CommonNapi::SetPropertyInt32(napi_env env, napi_value &obj, const std::string &key, int32_t value)
476 {
477 CHECK_AND_RETURN_RET(obj != nullptr, false);
478
479 napi_value keyNapi = nullptr;
480 napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
481 CHECK_AND_RETURN_RET(status == napi_ok, false);
482
483 napi_value valueNapi = nullptr;
484 status = napi_create_int32(env, value, &valueNapi);
485 CHECK_AND_RETURN_RET(status == napi_ok, false);
486
487 status = napi_set_property(env, obj, keyNapi, valueNapi);
488 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
489
490 return true;
491 }
492
SetPropertyInt64(napi_env env,napi_value & obj,const std::string & key,int64_t value)493 bool CommonNapi::SetPropertyInt64(napi_env env, napi_value &obj, const std::string &key, int64_t value)
494 {
495 CHECK_AND_RETURN_RET(obj != nullptr, false);
496
497 napi_value keyNapi = nullptr;
498 napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
499 CHECK_AND_RETURN_RET(status == napi_ok, false);
500
501 napi_value valueNapi = nullptr;
502 status = napi_create_int64(env, value, &valueNapi);
503 CHECK_AND_RETURN_RET(status == napi_ok, false);
504
505 status = napi_set_property(env, obj, keyNapi, valueNapi);
506 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
507
508 return true;
509 }
510
SetPropertyDouble(napi_env env,napi_value & obj,const std::string & key,double value)511 bool CommonNapi::SetPropertyDouble(napi_env env, napi_value &obj, const std::string &key, double value)
512 {
513 CHECK_AND_RETURN_RET(obj != nullptr, false);
514
515 napi_value keyNapi = nullptr;
516 napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
517 CHECK_AND_RETURN_RET(status == napi_ok, false);
518
519 napi_value valueNapi = nullptr;
520 status = napi_create_double(env, value, &valueNapi);
521 CHECK_AND_RETURN_RET(status == napi_ok, false);
522
523 status = napi_set_property(env, obj, keyNapi, valueNapi);
524 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
525
526 return true;
527 }
528
SetPropertyBool(napi_env env,napi_value & obj,const std::string & key,bool value)529 bool CommonNapi::SetPropertyBool(napi_env env, napi_value &obj, const std::string &key, bool value)
530 {
531 CHECK_AND_RETURN_RET(obj != nullptr, false);
532
533 napi_value keyNapi = nullptr;
534 napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
535 CHECK_AND_RETURN_RET(status == napi_ok, false);
536
537 napi_value valueNapi = nullptr;
538 status = napi_get_boolean(env, value, &valueNapi);
539 CHECK_AND_RETURN_RET(status == napi_ok, false);
540
541 status = napi_set_property(env, obj, keyNapi, valueNapi);
542 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
543
544 return true;
545 }
546
SetPropertyString(napi_env env,napi_value & obj,const std::string & key,const std::string & value)547 bool CommonNapi::SetPropertyString(napi_env env, napi_value &obj, const std::string &key, const std::string &value)
548 {
549 CHECK_AND_RETURN_RET(obj != nullptr, false);
550
551 napi_value keyNapi = nullptr;
552 napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
553 CHECK_AND_RETURN_RET(status == napi_ok, false);
554
555 napi_value valueNapi = nullptr;
556 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &valueNapi);
557 CHECK_AND_RETURN_RET(status == napi_ok, false);
558
559 status = napi_set_property(env, obj, keyNapi, valueNapi);
560 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "failed to set property");
561
562 return true;
563 }
564
CreateFormatBuffer(napi_env env,Format & format)565 napi_value CommonNapi::CreateFormatBuffer(napi_env env, Format &format)
566 {
567 napi_value buffer = nullptr;
568 int32_t intValue = 0;
569 std::string strValue;
570 napi_status status = napi_create_object(env, &buffer);
571 CHECK_AND_RETURN_RET(status == napi_ok, nullptr);
572
573 for (auto &iter : format.GetFormatMap()) {
574 switch (format.GetValueType(std::string_view(iter.first))) {
575 case FORMAT_TYPE_INT32:
576 if (format.GetIntValue(iter.first, intValue)) {
577 CHECK_AND_RETURN_RET(SetPropertyInt32(env, buffer, iter.first, intValue) == true, nullptr);
578 }
579 break;
580 case FORMAT_TYPE_INT64:
581 int64_t longValue;
582 if (format.GetLongValue(iter.first, longValue) &&
583 longValue >= INT32_MIN && longValue <= INT32_MAX) {
584 intValue = static_cast<int32_t>(longValue);
585 CHECK_AND_RETURN_RET(SetPropertyInt32(env, buffer, iter.first, intValue) == true, nullptr);
586 }
587 break;
588 case FORMAT_TYPE_DOUBLE:
589 double doubleValue;
590 if (format.GetDoubleValue(iter.first, doubleValue) &&
591 doubleValue >= INT32_MIN && doubleValue <= INT32_MAX) {
592 intValue = static_cast<int32_t>(doubleValue);
593 CHECK_AND_RETURN_RET(SetPropertyInt32(env, buffer, iter.first, intValue) == true, nullptr);
594 }
595 break;
596 case FORMAT_TYPE_STRING:
597 if (format.GetStringValue(iter.first, strValue)) {
598 CHECK_AND_RETURN_RET(SetPropertyString(env, buffer, iter.first, strValue) == true, nullptr);
599 }
600 break;
601 default:
602 MEDIA_LOGE("format key: %{public}s", iter.first.c_str());
603 break;
604 }
605 }
606
607 return buffer;
608 }
609
CreateFormatBufferByRef(napi_env env,Format & format,napi_value & result)610 bool CommonNapi::CreateFormatBufferByRef(napi_env env, Format &format, napi_value &result)
611 {
612 int32_t intValue = 0;
613 int64_t longValue = 0;
614 std::string strValue = "";
615 napi_status status = napi_create_object(env, &result);
616 CHECK_AND_RETURN_RET(status == napi_ok, false);
617
618 for (auto &iter : format.GetFormatMap()) {
619 switch (format.GetValueType(std::string_view(iter.first))) {
620 case FORMAT_TYPE_INT32:
621 if (format.GetIntValue(iter.first, intValue)) {
622 (void)SetPropertyInt32(env, result, iter.first, intValue);
623 }
624 break;
625 case FORMAT_TYPE_INT64:
626 if (format.GetLongValue(iter.first, longValue)) {
627 (void)SetPropertyInt64(env, result, iter.first, longValue);
628 }
629 break;
630 case FORMAT_TYPE_STRING:
631 if (format.GetStringValue(iter.first, strValue)) {
632 (void)SetPropertyString(env, result, iter.first, strValue);
633 }
634 break;
635 default:
636 MEDIA_LOGE("format key: %{public}s", iter.first.c_str());
637 break;
638 }
639 }
640
641 return true;
642 }
643
AddNumberPropInt32(napi_env env,napi_value obj,const std::string & key,int32_t value)644 bool CommonNapi::AddNumberPropInt32(napi_env env, napi_value obj, const std::string &key, int32_t value)
645 {
646 CHECK_AND_RETURN_RET(obj != nullptr, false);
647
648 napi_value keyNapi = nullptr;
649 napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
650 CHECK_AND_RETURN_RET(status == napi_ok, false);
651
652 napi_value valueNapi = nullptr;
653 status = napi_create_int32(env, value, &valueNapi);
654 CHECK_AND_RETURN_RET(status == napi_ok, false);
655
656 status = napi_set_property(env, obj, keyNapi, valueNapi);
657 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "Failed to set property");
658
659 return true;
660 }
661
AddNumberPropInt64(napi_env env,napi_value obj,const std::string & key,int64_t value)662 bool CommonNapi::AddNumberPropInt64(napi_env env, napi_value obj, const std::string &key, int64_t value)
663 {
664 CHECK_AND_RETURN_RET(obj != nullptr, false);
665
666 napi_value keyNapi = nullptr;
667 napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
668 CHECK_AND_RETURN_RET(status == napi_ok, false);
669
670 napi_value valueNapi = nullptr;
671 status = napi_create_int64(env, value, &valueNapi);
672 CHECK_AND_RETURN_RET(status == napi_ok, false);
673
674 status = napi_set_property(env, obj, keyNapi, valueNapi);
675 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "Failed to set property");
676
677 return true;
678 }
679
GetJsResult(napi_env env,napi_value & result)680 napi_status MediaJsResultStringVector::GetJsResult(napi_env env, napi_value &result)
681 {
682 napi_status status;
683 size_t size = value_.size();
684 napi_create_array_with_length(env, size, &result);
685 for (unsigned int i = 0; i < size; ++i) {
686 std::string format = value_[i];
687 napi_value value = nullptr;
688 status = napi_create_string_utf8(env, format.c_str(), NAPI_AUTO_LENGTH, &value);
689 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status,
690 "Failed to call napi_create_string_utf8, with element %{public}u", i);
691 status = napi_set_element(env, result, i, value);
692 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status,
693 "Failed to call napi_set_element, with element %{public}u", i);
694 }
695 return napi_ok;
696 }
697
GetJsResult(napi_env env,napi_value & result)698 napi_status MediaJsResultIntArray::GetJsResult(napi_env env, napi_value &result)
699 {
700 napi_status status;
701 size_t size = value_.size();
702 napi_create_array_with_length(env, size, &result);
703 for (unsigned int i = 0; i < size; ++i) {
704 int32_t index = value_[i];
705 napi_value value = nullptr;
706 status = napi_create_int32(env, index, &value);
707 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status,
708 "Failed to call napi_create_int32, with element %{public}u", i);
709 status = napi_set_element(env, result, i, value);
710 CHECK_AND_RETURN_RET_LOG(status == napi_ok, status,
711 "Failed to call napi_set_element, with element %{public}u", i);
712 }
713 return napi_ok;
714 }
715
GetJsResult(napi_env env,napi_value & result)716 napi_status MediaJsResultArray::GetJsResult(napi_env env, napi_value &result)
717 {
718 // create Description
719 napi_status status = napi_create_array(env, &result);
720 if (status != napi_ok) {
721 return napi_cancelled;
722 }
723
724 auto vecSize = value_.size();
725 for (size_t index = 0; index < vecSize; ++index) {
726 napi_value description = nullptr;
727 description = CommonNapi::CreateFormatBuffer(env, value_[index]);
728 if (description == nullptr || napi_set_element(env, result, index, description) != napi_ok) {
729 return napi_cancelled;
730 }
731 }
732 return napi_ok;
733 }
734
MediaAsyncContext(napi_env env)735 MediaAsyncContext::MediaAsyncContext(napi_env env)
736 : env_(env)
737 {
738 MEDIA_LOGD("MediaAsyncContext Create 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
739 }
740
~MediaAsyncContext()741 MediaAsyncContext::~MediaAsyncContext()
742 {
743 MEDIA_LOGD("MediaAsyncContext Destroy 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
744 }
745
SignError(int32_t code,const std::string & message,bool del)746 void MediaAsyncContext::SignError(int32_t code, const std::string &message, bool del)
747 {
748 errMessage = message;
749 errCode = code;
750 errFlag = true;
751 delFlag = del;
752 MEDIA_LOGE("SignError: %{public}s", message.c_str());
753 }
754
CompleteCallback(napi_env env,napi_status status,void * data)755 void MediaAsyncContext::CompleteCallback(napi_env env, napi_status status, void *data)
756 {
757 MEDIA_LOGD("CompleteCallback In");
758 auto asyncContext = reinterpret_cast<MediaAsyncContext *>(data);
759 CHECK_AND_RETURN_LOG(asyncContext != nullptr, "asyncContext is nullptr!");
760
761 std::string memoryTag = asyncContext->memoryTagHead + asyncContext->memoryTagTail;
762 MEDIA_LOGD("MediaAsyncContext Create 0x%{public}06" PRIXPTR " memoryTag = %{public}s",
763 FAKE_POINTER(data), memoryTag.c_str());
764
765 if (status != napi_ok) {
766 asyncContext->SignError(MSERR_EXT_UNKNOWN, "napi_create_async_work status != napi_ok");
767 }
768
769 napi_value result = nullptr;
770 napi_get_undefined(env, &result);
771 napi_value args[2] = { nullptr };
772 napi_get_undefined(env, &args[0]);
773 napi_get_undefined(env, &args[1]);
774 if (asyncContext->errFlag) {
775 MEDIA_LOGD("async callback failed");
776 (void)CommonNapi::CreateError(env, asyncContext->errCode, asyncContext->errMessage, result);
777 args[0] = result;
778 } else {
779 MEDIA_LOGD("async callback success");
780 if (asyncContext->JsResult != nullptr) {
781 asyncContext->JsResult->GetJsResult(env, result);
782 CheckCtorResult(env, result, asyncContext, args[0]);
783 }
784 if (!asyncContext->errFlag) {
785 args[1] = result;
786 }
787 }
788
789 Callback(env, asyncContext, args);
790 napi_delete_async_work(env, asyncContext->work);
791
792 if (asyncContext->delFlag) {
793 delete asyncContext;
794 asyncContext = nullptr;
795 }
796 }
797
Callback(napi_env env,const MediaAsyncContext * context,const napi_value * args)798 void MediaAsyncContext::Callback(napi_env env, const MediaAsyncContext *context, const napi_value *args)
799 {
800 if (context->deferred) {
801 if (context->errFlag) {
802 MEDIA_LOGE("promise napi_reject_deferred");
803 napi_reject_deferred(env, context->deferred, args[0]);
804 } else {
805 MEDIA_LOGD("promise napi_resolve_deferred");
806 napi_resolve_deferred(env, context->deferred, args[1]);
807 }
808 } else if (context->callbackRef != nullptr) {
809 MEDIA_LOGD("callback napi_call_function");
810 napi_value callback = nullptr;
811 napi_get_reference_value(env, context->callbackRef, &callback);
812 CHECK_AND_RETURN_LOG(callback != nullptr, "callback is nullptr!");
813 constexpr size_t argCount = 2;
814 napi_value retVal;
815 napi_get_undefined(env, &retVal);
816 napi_call_function(env, nullptr, callback, argCount, args, &retVal);
817 napi_delete_reference(env, context->callbackRef);
818 } else {
819 MEDIA_LOGE("invalid promise and callback");
820 }
821 }
822
CheckCtorResult(napi_env env,napi_value & result,MediaAsyncContext * ctx,napi_value & args)823 void MediaAsyncContext::CheckCtorResult(napi_env env, napi_value &result, MediaAsyncContext *ctx, napi_value &args)
824 {
825 CHECK_AND_RETURN(ctx != nullptr);
826 if (ctx->ctorFlag) {
827 void *instance = nullptr;
828 if (napi_unwrap(env, result, reinterpret_cast<void **>(&instance)) != napi_ok || instance == nullptr) {
829 MEDIA_LOGE("Failed to create instance");
830 ctx->errFlag = true;
831 (void)CommonNapi::CreateError(env, MSERR_EXT_API9_NO_MEMORY,
832 "The instance or memory has reached the upper limit, please recycle background playback", result);
833 args = result;
834 }
835 }
836 }
837
AddStringProperty(napi_env env,napi_value obj,const std::string & key,const std::string & value)838 bool CommonNapi::AddStringProperty(napi_env env, napi_value obj, const std::string &key, const std::string &value)
839 {
840 CHECK_AND_RETURN_RET(obj != nullptr, false);
841
842 napi_value keyNapi = nullptr;
843 napi_status status = napi_create_string_utf8(env, key.c_str(), NAPI_AUTO_LENGTH, &keyNapi);
844 CHECK_AND_RETURN_RET(status == napi_ok, false);
845
846 napi_value valueNapi = nullptr;
847 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &valueNapi);
848 CHECK_AND_RETURN_RET(status == napi_ok, false);
849
850 status = napi_set_property(env, obj, keyNapi, valueNapi);
851 CHECK_AND_RETURN_RET_LOG(status == napi_ok, false, "Failed to set property");
852
853 return true;
854 }
855
GetPropertyBool(napi_env env,napi_value configObj,const std::string & type,bool & result)856 bool CommonNapi::GetPropertyBool(napi_env env, napi_value configObj, const std::string &type, bool &result)
857 {
858 bool exist = false;
859 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
860 if (status != napi_ok || !exist) {
861 MEDIA_LOGE("can not find %{public}s property", type.c_str());
862 return false;
863 }
864 napi_value item = nullptr;
865 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
866 MEDIA_LOGE("get %{public}s property fail", type.c_str());
867 return false;
868 }
869 if (napi_get_value_bool(env, item, &result) != napi_ok) {
870 MEDIA_LOGE("get %{public}s property value fail", type.c_str());
871 return false;
872 }
873 return true;
874 }
875
ConvertDeviceInfoToAudioDeviceDescriptor(sptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor,const AudioStandard::DeviceInfo & deviceInfo)876 void CommonNapi::ConvertDeviceInfoToAudioDeviceDescriptor(
877 sptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor, const AudioStandard::DeviceInfo &deviceInfo)
878 {
879 CHECK_AND_RETURN_LOG(audioDeviceDescriptor != nullptr, "audioDeviceDescriptor is nullptr");
880 audioDeviceDescriptor->deviceRole_ = deviceInfo.deviceRole;
881 audioDeviceDescriptor->deviceType_ = deviceInfo.deviceType;
882 audioDeviceDescriptor->deviceId_ = deviceInfo.deviceId;
883 audioDeviceDescriptor->channelMasks_ = deviceInfo.channelMasks;
884 audioDeviceDescriptor->channelIndexMasks_ = deviceInfo.channelIndexMasks;
885 audioDeviceDescriptor->deviceName_ = deviceInfo.deviceName;
886 audioDeviceDescriptor->macAddress_ = deviceInfo.macAddress;
887 audioDeviceDescriptor->interruptGroupId_ = deviceInfo.interruptGroupId;
888 audioDeviceDescriptor->volumeGroupId_ = deviceInfo.volumeGroupId;
889 audioDeviceDescriptor->networkId_ = deviceInfo.networkId;
890 audioDeviceDescriptor->displayName_ = deviceInfo.displayName;
891 audioDeviceDescriptor->audioStreamInfo_.samplingRate = deviceInfo.audioStreamInfo.samplingRate;
892 audioDeviceDescriptor->audioStreamInfo_.encoding = deviceInfo.audioStreamInfo.encoding;
893 audioDeviceDescriptor->audioStreamInfo_.format = deviceInfo.audioStreamInfo.format;
894 audioDeviceDescriptor->audioStreamInfo_.channels = deviceInfo.audioStreamInfo.channels;
895 }
896
SetDeviceDescriptor(const napi_env & env,const AudioStandard::AudioDeviceDescriptor & deviceInfo,napi_value & result)897 napi_status CommonNapi::SetDeviceDescriptor(const napi_env &env, const AudioStandard::AudioDeviceDescriptor &deviceInfo,
898 napi_value &result)
899 {
900 (void)napi_create_object(env, &result);
901 SetPropertyInt32(env, result, "deviceRole", static_cast<int32_t>(deviceInfo.deviceRole_));
902 SetPropertyInt32(env, result, "deviceType", static_cast<int32_t>(deviceInfo.deviceType_));
903 SetPropertyInt32(env, result, "id", static_cast<int32_t>(deviceInfo.deviceId_));
904 SetPropertyString(env, result, "name", deviceInfo.deviceName_);
905 SetPropertyString(env, result, "address", deviceInfo.macAddress_);
906 SetPropertyString(env, result, "networkId", deviceInfo.networkId_);
907 SetPropertyString(env, result, "displayName", deviceInfo.displayName_);
908 SetPropertyInt32(env, result, "interruptGroupId", static_cast<int32_t>(deviceInfo.interruptGroupId_));
909 SetPropertyInt32(env, result, "volumeGroupId", static_cast<int32_t>(deviceInfo.volumeGroupId_));
910
911 napi_value value = nullptr;
912 napi_value sampleRates;
913 size_t size = deviceInfo.audioStreamInfo_.samplingRate.size();
914 napi_create_array_with_length(env, size, &sampleRates);
915 size_t count = 0;
916 for (const auto &samplingRate : deviceInfo.audioStreamInfo_.samplingRate) {
917 napi_create_int32(env, samplingRate, &value);
918 napi_set_element(env, sampleRates, count, value);
919 count++;
920 }
921 napi_set_named_property(env, result, "sampleRates", sampleRates);
922
923 napi_value channelCounts;
924 size = deviceInfo.audioStreamInfo_.channels.size();
925 napi_create_array_with_length(env, size, &channelCounts);
926 count = 0;
927 for (const auto &channels : deviceInfo.audioStreamInfo_.channels) {
928 napi_create_int32(env, channels, &value);
929 napi_set_element(env, channelCounts, count, value);
930 count++;
931 }
932 napi_set_named_property(env, result, "channelCounts", channelCounts);
933
934 std::vector<int32_t> channelMasks_;
935 channelMasks_.push_back(deviceInfo.channelMasks_);
936 AddArrayProperty(env, result, "channelMasks", channelMasks_);
937
938 std::vector<int32_t> channelIndexMasks_;
939 channelIndexMasks_.push_back(deviceInfo.channelIndexMasks_);
940 AddArrayProperty(env, result, "channelIndexMasks", channelIndexMasks_);
941
942 std::vector<int32_t> encoding;
943 encoding.push_back(deviceInfo.audioStreamInfo_.encoding);
944 AddArrayProperty(env, result, "encodingTypes", encoding);
945
946 return napi_ok;
947 }
948
SetDeviceDescriptors(const napi_env & env,const std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> & deviceDescriptors,napi_value & result)949 napi_status CommonNapi::SetDeviceDescriptors(const napi_env &env,
950 const std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> &deviceDescriptors, napi_value &result)
951 {
952 napi_status status = napi_create_array_with_length(env, deviceDescriptors.size(), &result);
953 for (size_t i = 0; i < deviceDescriptors.size(); i++) {
954 if (deviceDescriptors[i] != nullptr) {
955 napi_value valueParam = nullptr;
956 SetDeviceDescriptor(env, deviceDescriptors[i], valueParam);
957 napi_set_element(env, result, i, valueParam);
958 }
959 }
960 return status;
961 }
962
SetValueDeviceInfo(const napi_env & env,const AudioStandard::DeviceInfo & deviceInfo,napi_value & result)963 napi_status CommonNapi::SetValueDeviceInfo(const napi_env &env, const AudioStandard::DeviceInfo &deviceInfo,
964 napi_value &result)
965 {
966 std::vector<sptr<AudioStandard::AudioDeviceDescriptor>> deviceDescriptors;
967 sptr<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptor =
968 new(std::nothrow) AudioStandard::AudioDeviceDescriptor();
969 CHECK_AND_RETURN_RET_LOG(audioDeviceDescriptor != nullptr, napi_generic_failure,
970 "audioDeviceDescriptor malloc failed");
971 ConvertDeviceInfoToAudioDeviceDescriptor(audioDeviceDescriptor, deviceInfo);
972 deviceDescriptors.push_back(std::move(audioDeviceDescriptor));
973 SetDeviceDescriptors(env, deviceDescriptors, result);
974 return napi_ok;
975 }
976 } // namespace Media
977 } // namespace OHOS