1 /*
2 * Copyright (c) 2022 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 "napi_meta_data.h"
17 #include "avsession_log.h"
18 #include "avsession_pixel_map_adapter.h"
19 #include "napi_utils.h"
20 #include "pixel_map_napi.h"
21
22 namespace OHOS::AVSession {
23 std::map<std::string, NapiMetaData::GetterType> NapiMetaData::getterMap_ = {
24 { "assetId", GetAssetId },
25 { "title", GetTitle },
26 { "artist", GetArtist },
27 { "author", GetAuthor },
28 { "album", GetAlbum },
29 { "writer", GetWriter },
30 { "composer", GetComposer },
31 { "duration", GetDuration },
32 { "mediaImage", GetMediaImage },
33 { "publishDate", GetPublishDate },
34 { "subtitle", GetSubtitle },
35 { "description", GetDescription },
36 { "lyric", GetLyric },
37 { "previousAssetId", GetPreviousAssetId },
38 { "nextAssetId", GetNextAssetId }
39 };
40
41 std::map<int32_t, NapiMetaData::SetterType> NapiMetaData::setterMap_ = {
42 { AVMetaData::META_KEY_ASSET_ID, SetAssetId },
43 { AVMetaData::META_KEY_TITLE, SetTitle },
44 { AVMetaData::META_KEY_ARTIST, SetArtist },
45 { AVMetaData::META_KEY_AUTHOR, SetAuthor },
46 { AVMetaData::META_KEY_ALBUM, SetAlbum },
47 { AVMetaData::META_KEY_WRITER, SetWriter },
48 { AVMetaData::META_KEY_COMPOSER, SetComposer },
49 { AVMetaData::META_KEY_DURATION, SetDuration },
50 { AVMetaData::META_KEY_MEDIA_IMAGE, SetMediaImage },
51 { AVMetaData::META_KEY_MEDIA_IMAGE_URI, SetMediaImageUri },
52 { AVMetaData::META_KEY_PUBLISH_DATE, SetPublishDate },
53 { AVMetaData::META_KEY_SUBTITLE, SetSubtitle },
54 { AVMetaData::META_KEY_DESCRIPTION, SetDescription },
55 { AVMetaData::META_KEY_LYRIC, SetLyric },
56 { AVMetaData::META_KEY_PREVIOUS_ASSET_ID, SetPreviousAssetId },
57 { AVMetaData::META_KEY_NEXT_ASSET_ID, SetNextAssetId },
58 };
59
60 std::pair<std::string, int32_t> NapiMetaData::filterMap_[] = {
61 { "assetId", AVMetaData::META_KEY_ASSET_ID },
62 { "title", AVMetaData::META_KEY_TITLE },
63 { "artist", AVMetaData::META_KEY_ARTIST },
64 { "author", AVMetaData::META_KEY_AUTHOR },
65 { "album", AVMetaData::META_KEY_ALBUM },
66 { "writer", AVMetaData::META_KEY_WRITER },
67 { "composer", AVMetaData::META_KEY_COMPOSER },
68 { "duration", AVMetaData::META_KEY_DURATION },
69 { "mediaImage", AVMetaData::META_KEY_MEDIA_IMAGE },
70 { "mediaImage", AVMetaData::META_KEY_MEDIA_IMAGE_URI },
71 { "publishDate", AVMetaData::META_KEY_PUBLISH_DATE },
72 { "subtitle", AVMetaData::META_KEY_SUBTITLE },
73 { "description", AVMetaData::META_KEY_DESCRIPTION },
74 { "lyric", AVMetaData::META_KEY_LYRIC },
75 { "previousAssetId", AVMetaData::META_KEY_PREVIOUS_ASSET_ID },
76 { "nextAssetId", AVMetaData::META_KEY_NEXT_ASSET_ID }
77 };
78
ConvertFilter(napi_env env,napi_value filter,AVMetaData::MetaMaskType & mask)79 napi_status NapiMetaData::ConvertFilter(napi_env env, napi_value filter, AVMetaData::MetaMaskType& mask)
80 {
81 napi_valuetype type = napi_undefined;
82 auto status = napi_typeof(env, filter, &type);
83 CHECK_RETURN(status == napi_ok, "napi_typeof failed", status);
84
85 if (type == napi_string) {
86 std::string stringFilter;
87 status = NapiUtils::GetValue(env, filter, stringFilter);
88 CHECK_RETURN(status == napi_ok, "get string filter failed", status);
89 if (stringFilter != "all") {
90 SLOGE("string filter only support all") ;
91 return napi_invalid_arg;
92 }
93 mask.set();
94 return napi_ok;
95 }
96
97 uint32_t count = 0;
98 status = napi_get_array_length(env, filter, &count);
99 CHECK_RETURN(status == napi_ok, "get array length failed", status);
100 for (uint32_t i = 0; i < count; i++) {
101 napi_value value {};
102 status = napi_get_element(env, filter, i, &value);
103 CHECK_RETURN(status == napi_ok, "get element failed", status);
104 std::string metaKey;
105 status = NapiUtils::GetValue(env, value, metaKey);
106 CHECK_RETURN(status == napi_ok, "get string value failed", status);
107 for (const auto& pair : filterMap_) {
108 if (pair.first == metaKey) {
109 mask.set(pair.second);
110 }
111 }
112 }
113
114 return napi_ok;
115 }
116
GetValue(napi_env env,napi_value in,AVMetaData & out)117 napi_status NapiMetaData::GetValue(napi_env env, napi_value in, AVMetaData& out)
118 {
119 std::vector<std::string> propertyNames;
120 auto status = NapiUtils::GetPropertyNames(env, in, propertyNames);
121 CHECK_RETURN(status == napi_ok, "get property name failed", status);
122
123 for (const auto& name : propertyNames) {
124 auto it = getterMap_.find(name);
125 if (it == getterMap_.end()) {
126 SLOGE("property %{public}s is not of metadata", name.c_str());
127 return napi_invalid_arg;
128 }
129 auto getter = it->second;
130 if (getter(env, in, out) != napi_ok) {
131 SLOGE("get property %{public}s failed", name.c_str());
132 return napi_generic_failure;
133 }
134 }
135
136 return napi_ok;
137 }
138
SetValue(napi_env env,const AVMetaData & in,napi_value & out)139 napi_status NapiMetaData::SetValue(napi_env env, const AVMetaData& in, napi_value& out)
140 {
141 napi_status status = napi_create_object(env, &out);
142 CHECK_RETURN((status == napi_ok) && (out != nullptr), "create object failed", status);
143
144 auto mask = in.GetMetaMask();
145 if (mask.none()) {
146 SLOGI("undefined meta");
147 return SetUndefinedMeta(env, out);
148 }
149
150 for (int i = 0; i < AVMetaData::META_KEY_MAX; ++i) {
151 if (!mask.test(i)) {
152 continue;
153 }
154 auto setter = setterMap_[i];
155 if (setter(env, in, out) != napi_ok) {
156 SLOGE("set property %{public}d failed", i);
157 return napi_generic_failure;
158 }
159 }
160
161 return napi_ok;
162 }
163
SetUndefinedMeta(napi_env env,napi_value & meta)164 napi_status NapiMetaData::SetUndefinedMeta(napi_env env, napi_value& meta)
165 {
166 auto status = napi_set_named_property(env, meta, "assetId", NapiUtils::GetUndefinedValue(env));
167 CHECK_RETURN(status == napi_ok, "set assetId to undefined failed", status);
168 return napi_ok;
169 }
170
GetAssetId(napi_env env,napi_value in,AVMetaData & out)171 napi_status NapiMetaData::GetAssetId(napi_env env, napi_value in, AVMetaData& out)
172 {
173 std::string property;
174 auto status = NapiUtils::GetNamedProperty(env, in, "assetId", property);
175 CHECK_RETURN(status == napi_ok, "get property failed", status);
176 out.SetAssetId(property);
177 return status;
178 }
179
SetAssetId(napi_env env,const AVMetaData & in,napi_value & out)180 napi_status NapiMetaData::SetAssetId(napi_env env, const AVMetaData& in, napi_value& out)
181 {
182 napi_value property {};
183 auto status = NapiUtils::SetValue(env, in.GetAssetId(), property);
184 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
185 status = napi_set_named_property(env, out, "assetId", property);
186 CHECK_RETURN(status == napi_ok, "set property failed", status);
187 return status;
188 }
189
GetTitle(napi_env env,napi_value in,AVMetaData & out)190 napi_status NapiMetaData::GetTitle(napi_env env, napi_value in, AVMetaData& out)
191 {
192 std::string property;
193 auto status = NapiUtils::GetNamedProperty(env, in, "title", property);
194 CHECK_RETURN(status == napi_ok, "get property failed", status);
195 out.SetTitle(property);
196 return status;
197 }
198
SetTitle(napi_env env,const AVMetaData & in,napi_value & out)199 napi_status NapiMetaData::SetTitle(napi_env env, const AVMetaData& in, napi_value& out)
200 {
201 napi_value property {};
202 auto status = NapiUtils::SetValue(env, in.GetTitle(), property);
203 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
204 status = napi_set_named_property(env, out, "title", property);
205 CHECK_RETURN(status == napi_ok, "set property failed", status);
206 return status;
207 }
208
GetArtist(napi_env env,napi_value in,AVMetaData & out)209 napi_status NapiMetaData::GetArtist(napi_env env, napi_value in, AVMetaData& out)
210 {
211 std::string property;
212 auto status = NapiUtils::GetNamedProperty(env, in, "artist", property);
213 CHECK_RETURN(status == napi_ok, "get property failed", status);
214 out.SetArtist(property);
215 return status;
216 }
217
SetArtist(napi_env env,const AVMetaData & in,napi_value & out)218 napi_status NapiMetaData::SetArtist(napi_env env, const AVMetaData& in, napi_value& out)
219 {
220 napi_value property {};
221 auto status = NapiUtils::SetValue(env, in.GetArtist(), property);
222 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
223 status = napi_set_named_property(env, out, "artist", property);
224 CHECK_RETURN(status == napi_ok, "set property failed", status);
225 return status;
226 }
227
GetAuthor(napi_env env,napi_value in,AVMetaData & out)228 napi_status NapiMetaData::GetAuthor(napi_env env, napi_value in, AVMetaData& out)
229 {
230 std::string property;
231 auto status = NapiUtils::GetNamedProperty(env, in, "author", property);
232 CHECK_RETURN(status == napi_ok, "get property failed", status);
233 out.SetAuthor(property);
234 return status;
235 }
236
SetAuthor(napi_env env,const AVMetaData & in,napi_value & out)237 napi_status NapiMetaData::SetAuthor(napi_env env, const AVMetaData& in, napi_value& out)
238 {
239 napi_value property {};
240 auto status = NapiUtils::SetValue(env, in.GetAuthor(), property);
241 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
242 status = napi_set_named_property(env, out, "author", property);
243 CHECK_RETURN(status == napi_ok, "set property failed", status);
244 return status;
245 }
246
GetAlbum(napi_env env,napi_value in,AVMetaData & out)247 napi_status NapiMetaData::GetAlbum(napi_env env, napi_value in, AVMetaData& out)
248 {
249 std::string property;
250 auto status = NapiUtils::GetNamedProperty(env, in, "album", property);
251 CHECK_RETURN(status == napi_ok, "get property failed", status);
252 out.SetAlbum(property);
253 return status;
254 }
255
SetAlbum(napi_env env,const AVMetaData & in,napi_value & out)256 napi_status NapiMetaData::SetAlbum(napi_env env, const AVMetaData& in, napi_value& out)
257 {
258 napi_value property {};
259 auto status = NapiUtils::SetValue(env, in.GetAlbum(), property);
260 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
261 status = napi_set_named_property(env, out, "album", property);
262 CHECK_RETURN(status == napi_ok, "set property failed", status);
263 return status;
264 }
265
GetWriter(napi_env env,napi_value in,AVMetaData & out)266 napi_status NapiMetaData::GetWriter(napi_env env, napi_value in, AVMetaData& out)
267 {
268 std::string property;
269 auto status = NapiUtils::GetNamedProperty(env, in, "writer", property);
270 CHECK_RETURN(status == napi_ok, "get property failed", status);
271 out.SetWriter(property);
272 return status;
273 }
274
SetWriter(napi_env env,const AVMetaData & in,napi_value & out)275 napi_status NapiMetaData::SetWriter(napi_env env, const AVMetaData& in, napi_value& out)
276 {
277 napi_value property {};
278 auto status = NapiUtils::SetValue(env, in.GetWriter(), property);
279 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
280 status = napi_set_named_property(env, out, "writer", property);
281 CHECK_RETURN(status == napi_ok, "set property failed", status);
282 return status;
283 }
284
GetComposer(napi_env env,napi_value in,AVMetaData & out)285 napi_status NapiMetaData::GetComposer(napi_env env, napi_value in, AVMetaData& out)
286 {
287 std::string property;
288 auto status = NapiUtils::GetNamedProperty(env, in, "composer", property);
289 CHECK_RETURN(status == napi_ok, "get property failed", status);
290 out.SetComposer(property);
291 return status;
292 }
293
SetComposer(napi_env env,const AVMetaData & in,napi_value & out)294 napi_status NapiMetaData::SetComposer(napi_env env, const AVMetaData& in, napi_value& out)
295 {
296 napi_value property {};
297 auto status = NapiUtils::SetValue(env, in.GetComposer(), property);
298 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
299 status = napi_set_named_property(env, out, "composer", property);
300 CHECK_RETURN(status == napi_ok, "set property failed", status);
301 return status;
302 }
303
GetDuration(napi_env env,napi_value in,AVMetaData & out)304 napi_status NapiMetaData::GetDuration(napi_env env, napi_value in, AVMetaData& out)
305 {
306 int64_t property;
307 auto status = NapiUtils::GetNamedProperty(env, in, "duration", property);
308 CHECK_RETURN(status == napi_ok, "get property failed", status);
309 out.SetDuration(property);
310 return status;
311 }
312
SetDuration(napi_env env,const AVMetaData & in,napi_value & out)313 napi_status NapiMetaData::SetDuration(napi_env env, const AVMetaData& in, napi_value& out)
314 {
315 napi_value property {};
316 auto status = NapiUtils::SetValue(env, in.GetDuration(), property);
317 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
318 status = napi_set_named_property(env, out, "duration", property);
319 CHECK_RETURN(status == napi_ok, "set property failed", status);
320 return status;
321 }
322
GetMediaImage(napi_env env,napi_value in,AVMetaData & out)323 napi_status NapiMetaData::GetMediaImage(napi_env env, napi_value in, AVMetaData& out)
324 {
325 napi_value property {};
326 auto status = napi_get_named_property(env, in, "mediaImage", &property);
327 CHECK_RETURN((status == napi_ok) && (property != nullptr), "get property failed", status);
328 napi_valuetype type = napi_undefined;
329 status = napi_typeof(env, property, &type);
330 CHECK_RETURN(status == napi_ok, "get napi_value type failed", status);
331 if (type == napi_string) {
332 std::string uri;
333 status = NapiUtils::GetValue(env, property, uri);
334 CHECK_RETURN(status == napi_ok, "get property failed", status);
335 out.SetMediaImageUri(uri);
336 } else if (type == napi_object) {
337 auto pixelMap = Media::PixelMapNapi::GetPixelMap(env, property);
338 if (pixelMap == nullptr) {
339 SLOGE("unwrap failed");
340 return napi_invalid_arg;
341 }
342 out.SetMediaImage(AVSessionPixelMapAdapter::ConvertToInner(pixelMap));
343 } else {
344 SLOGE("mediaImage property value type invalid");
345 return napi_invalid_arg;
346 }
347
348 return status;
349 }
350
SetMediaImage(napi_env env,const AVMetaData & in,napi_value & out)351 napi_status NapiMetaData::SetMediaImage(napi_env env, const AVMetaData& in, napi_value& out)
352 {
353 auto pixelMap = in.GetMediaImage();
354 if (pixelMap == nullptr) {
355 SLOGI("media image is none");
356 return napi_ok;
357 }
358
359 napi_value property = Media::PixelMapNapi::CreatePixelMap(env,
360 AVSessionPixelMapAdapter::ConvertFromInner(pixelMap));
361 auto status = napi_set_named_property(env, out, "mediaImage", property);
362 CHECK_RETURN(status == napi_ok, "set property failed", status);
363 return status;
364 }
365
SetMediaImageUri(napi_env env,const AVMetaData & in,napi_value & out)366 napi_status NapiMetaData::SetMediaImageUri(napi_env env, const AVMetaData& in, napi_value& out)
367 {
368 auto uri = in.GetMediaImageUri();
369 if (uri.empty()) {
370 SLOGI("media image uri empty");
371 return napi_ok;
372 }
373
374 napi_value property {};
375 auto status = NapiUtils::SetValue(env, uri, property);
376 CHECK_RETURN(status == napi_ok, "create property failed", status);
377 status = napi_set_named_property(env, out, "mediaImage", property);
378 CHECK_RETURN(status == napi_ok, "set property failed", status);
379 return status;
380 }
381
GetPublishDate(napi_env env,napi_value in,AVMetaData & out)382 napi_status NapiMetaData::GetPublishDate(napi_env env, napi_value in, AVMetaData& out)
383 {
384 napi_value property;
385 auto status = napi_get_named_property(env, in, "publishDate", &property);
386 CHECK_RETURN(status == napi_ok, "get property failed", status);
387 double date {};
388 status = NapiUtils::GetDateValue(env, property, date);
389 CHECK_RETURN(status == napi_ok, "get date value failed", status);
390 out.SetPublishDate(date);
391 return status;
392 }
393
SetPublishDate(napi_env env,const AVMetaData & in,napi_value & out)394 napi_status NapiMetaData::SetPublishDate(napi_env env, const AVMetaData& in, napi_value& out)
395 {
396 napi_value property {};
397 auto status = NapiUtils::SetDateValue(env, in.GetPublishDate(), property);
398 CHECK_RETURN(status == napi_ok, "create date object failed", status);
399 status = napi_set_named_property(env, out, "publishDate", property);
400 CHECK_RETURN(status == napi_ok, "set property failed", status);
401 return status;
402 }
403
GetSubtitle(napi_env env,napi_value in,AVMetaData & out)404 napi_status NapiMetaData::GetSubtitle(napi_env env, napi_value in, AVMetaData& out)
405 {
406 std::string property;
407 auto status = NapiUtils::GetNamedProperty(env, in, "subtitle", property);
408 CHECK_RETURN(status == napi_ok, "get property failed", status);
409 out.SetSubTitle(property);
410 return status;
411 }
412
SetSubtitle(napi_env env,const AVMetaData & in,napi_value & out)413 napi_status NapiMetaData::SetSubtitle(napi_env env, const AVMetaData& in, napi_value& out)
414 {
415 napi_value property {};
416 auto status = NapiUtils::SetValue(env, in.GetSubTitle(), property);
417 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
418 status = napi_set_named_property(env, out, "subtitle", property);
419 CHECK_RETURN(status == napi_ok, "set property failed", status);
420 return status;
421 }
422
GetDescription(napi_env env,napi_value in,AVMetaData & out)423 napi_status NapiMetaData::GetDescription(napi_env env, napi_value in, AVMetaData& out)
424 {
425 std::string property;
426 auto status = NapiUtils::GetNamedProperty(env, in, "description", property);
427 CHECK_RETURN(status == napi_ok, "get property failed", status);
428 out.SetDescription(property);
429 return status;
430 }
431
SetDescription(napi_env env,const AVMetaData & in,napi_value & out)432 napi_status NapiMetaData::SetDescription(napi_env env, const AVMetaData& in, napi_value& out)
433 {
434 napi_value property {};
435 auto status = NapiUtils::SetValue(env, in.GetDescription(), property);
436 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
437 status = napi_set_named_property(env, out, "description", property);
438 CHECK_RETURN(status == napi_ok, "set property failed", status);
439 return status;
440 }
441
GetLyric(napi_env env,napi_value in,AVMetaData & out)442 napi_status NapiMetaData::GetLyric(napi_env env, napi_value in, AVMetaData& out)
443 {
444 std::string property;
445 auto status = NapiUtils::GetNamedProperty(env, in, "lyric", property);
446 CHECK_RETURN(status == napi_ok, "get property failed", status);
447 out.SetLyric(property);
448 return status;
449 }
450
SetLyric(napi_env env,const AVMetaData & in,napi_value & out)451 napi_status NapiMetaData::SetLyric(napi_env env, const AVMetaData& in, napi_value& out)
452 {
453 napi_value property {};
454 auto status = NapiUtils::SetValue(env, in.GetLyric(), property);
455 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
456 status = napi_set_named_property(env, out, "lyric", property);
457 CHECK_RETURN(status == napi_ok, "set property failed", status);
458 return status;
459 }
460
GetPreviousAssetId(napi_env env,napi_value in,AVMetaData & out)461 napi_status NapiMetaData::GetPreviousAssetId(napi_env env, napi_value in, AVMetaData& out)
462 {
463 std::string property;
464 auto status = NapiUtils::GetNamedProperty(env, in, "previousAssetId", property);
465 CHECK_RETURN(status == napi_ok, "get property failed", status);
466 out.SetPreviousAssetId(property);
467 return status;
468 }
469
SetPreviousAssetId(napi_env env,const AVMetaData & in,napi_value & out)470 napi_status NapiMetaData::SetPreviousAssetId(napi_env env, const AVMetaData& in, napi_value& out)
471 {
472 napi_value property {};
473 auto status = NapiUtils::SetValue(env, in.GetPreviousAssetId(), property);
474 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
475 status = napi_set_named_property(env, out, "previousAssetId", property);
476 CHECK_RETURN(status == napi_ok, "set property failed", status);
477 return status;
478 }
479
GetNextAssetId(napi_env env,napi_value in,AVMetaData & out)480 napi_status NapiMetaData::GetNextAssetId(napi_env env, napi_value in, AVMetaData& out)
481 {
482 std::string property;
483 auto status = NapiUtils::GetNamedProperty(env, in, "nextAssetId", property);
484 CHECK_RETURN(status == napi_ok, "get property failed", status);
485 out.SetNextAssetId(property);
486 return status;
487 }
488
SetNextAssetId(napi_env env,const AVMetaData & in,napi_value & out)489 napi_status NapiMetaData::SetNextAssetId(napi_env env, const AVMetaData& in, napi_value& out)
490 {
491 napi_value property {};
492 auto status = NapiUtils::SetValue(env, in.GetNextAssetId(), property);
493 CHECK_RETURN((status == napi_ok) && (property != nullptr), "create property failed", status);
494 status = napi_set_named_property(env, out, "nextAssetId", property);
495 CHECK_RETURN(status == napi_ok, "set property failed", status);
496 return status;
497 }
498 }