From c456a5ac54a63c06b48619f8889b38ac14c2e140 Mon Sep 17 00:00:00 2001
From: Piotr Kosko
Date: Wed, 30 Sep 2020 08:23:20 +0200
Subject: [PATCH] [Metadata] Added getArtwork method of MetadataFileHandle
[ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-271
[Verification]
Code compiles without errors.
Checked in chrome console with below code.
Precondition: sample.mp3 with artwork need to be pushed on device
// test artwork
var path = "videos/sample.mp3";
function showBlob(bbb) {
var elem = document.getElementById("blobImage") || document.createElement("img");
elem.setAttribute("id", "blobImage");
elem.setAttribute("height", "240");
elem.setAttribute("width", "240");
elem.setAttribute("alt", "invalid blob");
document.getElementById("test").appendChild(elem)
var objectURL = URL.createObjectURL(bbb);
elem.src = objectURL;
}
var fileHandle = tizen.metadata.createFileHandle(path);
var artwork = fileHandle.getArtwork();
console.log(artwork);
showBlob(artwork)
Change-Id: Ia0cbe5ade542ad71224a91c0c1a4618072b5538e
---
src/metadata/metadata_api.js | 33 ++++++++++
src/metadata/metadata_file_handle.cc | 30 ++++++++++
src/metadata/metadata_file_handle.h | 2 +
src/metadata/metadata_instance.cc | 90 ++++++++++++++++++++++++----
src/metadata/metadata_instance.h | 2 +
5 files changed, 145 insertions(+), 12 deletions(-)
diff --git a/src/metadata/metadata_api.js b/src/metadata/metadata_api.js
index fc3897b3..66a1fa65 100755
--- a/src/metadata/metadata_api.js
+++ b/src/metadata/metadata_api.js
@@ -125,5 +125,38 @@ MetadataFileHandle.prototype.release = function() {
return native_.getResultObject(result);
};
+// below section copied from filesystem
+// TODO move this to utils?
+/*
+ * Create new array-like object of numbers: UTF-16 char codes from string.
+ * As type pass Array, Uint8Array, etc.
+ * Useful for passing data through crosswalk.
+ */
+function StringToArray(str, type) {
+ var len = str.length;
+ var output = new type(len);
+ for (var i = 0; i < len; i++) {
+ output[i] = str.charCodeAt(i);
+ }
+ return output;
+}
+////////////////////////////////////////////////////
+
+MetadataFileHandle.prototype.getArtwork = function() {
+ var data = {
+ uri: this.uri,
+ id: this._id
+ };
+
+ var result = native_.callSync('MetadataFileHandleGetArtwork', data);
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+ var resultData = native_.getResultObject(result);
+ var encodedData = StringToArray(resultData.encodedData, Uint8Array);
+
+ return new Blob([encodedData], { type: resultData.mimeType });
+};
+
// Exports
exports = new MetadataManager();
diff --git a/src/metadata/metadata_file_handle.cc b/src/metadata/metadata_file_handle.cc
index 5f9dba99..1e40e4e5 100644
--- a/src/metadata/metadata_file_handle.cc
+++ b/src/metadata/metadata_file_handle.cc
@@ -19,6 +19,7 @@
#include "common/logger.h"
#include "common/platform_enum.h"
#include "common/platform_exception.h"
+#include "common/scope_exit.h"
namespace extension {
namespace metadata {
@@ -191,5 +192,34 @@ PlatformResult MetadataFileHandle::Get(const std::string& type, std::string* res
return PlatformResult(ErrorCode::NO_ERROR);
}
+PlatformResult MetadataFileHandle::GetArtwork(std::vector* artwork_array,
+ std::string* mime_type_str) {
+ ScopeLogger();
+ int size = 0;
+ void* artwork = nullptr;
+ char* mime_type = nullptr;
+ SCOPE_EXIT {
+ free(artwork);
+ free(mime_type);
+ };
+
+ int native_res = metadata_extractor_get_artwork(handle_, &artwork, &size, &mime_type);
+ if (METADATA_EXTRACTOR_ERROR_NONE != native_res) {
+ LoggerE("Error during getting metadata: %d", native_res);
+ return convertErrorCode(native_res);
+ }
+ LoggerD("Artwork size %d", size);
+
+ // convert artwork to vector
+ std::uint8_t* uint8_artwork = (std::uint8_t*)artwork;
+ std::vector out_buf(uint8_artwork, uint8_artwork + size);
+
+ // set results
+ *artwork_array = std::move(out_buf);
+ *mime_type_str = mime_type ? mime_type : "";
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
} // namespace metadata
} // namespace extension
diff --git a/src/metadata/metadata_file_handle.h b/src/metadata/metadata_file_handle.h
index bb16e181..67d31c54 100644
--- a/src/metadata/metadata_file_handle.h
+++ b/src/metadata/metadata_file_handle.h
@@ -38,6 +38,8 @@ class MetadataFileHandle {
common::PlatformResult Initialize(const std::string& uri);
common::PlatformResult Get(const std::string& type, std::string* result);
+ common::PlatformResult GetArtwork(std::vector* data, std::string* mime_type);
+
private:
metadata_extractor_h handle_;
int id_;
diff --git a/src/metadata/metadata_instance.cc b/src/metadata/metadata_instance.cc
index 5a90e2e0..5e1db6b8 100644
--- a/src/metadata/metadata_instance.cc
+++ b/src/metadata/metadata_instance.cc
@@ -34,6 +34,7 @@ MetadataInstance::MetadataInstance() : next_handle_id_(1) {
REGISTER_METHOD(MetadataManagerCreateFileHandle);
REGISTER_METHOD(MetadataFileHandleGet);
+ REGISTER_METHOD(MetadataFileHandleGetArtwork);
REGISTER_METHOD(MetadataFileHandleRelease);
#undef REGISTER_METHOD
}
@@ -58,16 +59,8 @@ void MetadataInstance::MetadataManagerCreateFileHandle(const picojson::value& ar
handles_map_.insert(std::pair(next_handle_id_++, std::move(m)));
}
-void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojson::object& out) {
+PlatformResult MetadataInstance::InitializeHandleIfNeeded(const std::string& uri, const int id) {
ScopeLogger();
- const std::string& uri = args.get("uri").get();
- const int id = static_cast(args.get("id").get());
- const std::string& type = args.get("type").get();
-
- LoggerD("File: %s getting metadata type: %s", uri.c_str(), type.c_str());
-
- std::string value;
-
auto it = handles_map_.find(id);
if (handles_map_.end() == it) {
LoggerD("Handle does not exist in map, creating new one");
@@ -77,13 +70,29 @@ void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojs
if (!res) {
// if everything works fine with a file, handle should be created successfully, as this is a
// re-creation. In case of errors, just return an AbortError
- LogAndReportError(
- PlatformResult(ErrorCode::ABORT_ERR, "Unknown error during accessing a file."), &out);
- return;
+ return LogAndCreateResult(ErrorCode::ABORT_ERR, "Unknown error during accessing a file.");
}
// store it in the map
handles_map_.insert(std::pair(id, std::move(m)));
}
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+ const std::string& uri = args.get("uri").get();
+ const int id = static_cast(args.get("id").get());
+ const std::string& type = args.get("type").get();
+
+ LoggerD("File: %s getting metadata type: %s", uri.c_str(), type.c_str());
+
+ std::string value;
+
+ auto res = InitializeHandleIfNeeded(uri, id);
+ if (!res) {
+ LogAndReportError(res, &out);
+ return;
+ }
try {
MetadataFileHandle& m = handles_map_.at(id);
@@ -102,6 +111,63 @@ void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojs
ReportSuccess(picojson::value(value), out);
}
+// TODO copied from filesystem
+// move to common??
+/* Write to str buf bytes as if they were UTF-8 codepoints */
+static void encode_binary_in_string(const std::vector& buf, std::string& str) {
+ ScopeLogger();
+ str.reserve(str.size() + buf.size());
+
+ for (std::uint8_t byte : buf) {
+ if (byte < 128) {
+ str += byte;
+ continue;
+ }
+ str += 0xC0 | (byte >> 6);
+ str += 0x80 | (byte & 0x3F);
+ }
+}
+///////////////////////////////////
+
+void MetadataInstance::MetadataFileHandleGetArtwork(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ const std::string& uri = args.get("uri").get();
+ const int id = static_cast(args.get("id").get());
+
+ auto res = InitializeHandleIfNeeded(uri, id);
+ if (!res) {
+ LogAndReportError(res, &out);
+ return;
+ }
+
+ std::vector data;
+ std::string mime_type;
+ try {
+ MetadataFileHandle& m = handles_map_.at(id);
+
+ auto res = m.GetArtwork(&data, &mime_type);
+ if (!res) {
+ LogAndReportError(res, &out);
+ return;
+ }
+ } catch (...) {
+ // this should never happen
+ LogAndReportError(
+ PlatformResult(ErrorCode::ABORT_ERR, "Unknown error during accessing a file."), &out);
+ return;
+ }
+
+ picojson::value result_artwork = picojson::value(picojson::object());
+ picojson::object& result_artwork_obj = result_artwork.get();
+
+ result_artwork_obj["encodedData"] = picojson::value(picojson::string_type, true);
+ encode_binary_in_string(data, result_artwork_obj["encodedData"].get());
+ result_artwork_obj["mimeType"] = picojson::value(mime_type);
+
+ ReportSuccess(result_artwork, out);
+}
+
void MetadataInstance::MetadataFileHandleRelease(const picojson::value& args,
picojson::object& out) {
ScopeLogger();
diff --git a/src/metadata/metadata_instance.h b/src/metadata/metadata_instance.h
index 694dbc1c..68eeddc4 100644
--- a/src/metadata/metadata_instance.h
+++ b/src/metadata/metadata_instance.h
@@ -30,7 +30,9 @@ class MetadataInstance : public common::ParsedInstance {
private:
void MetadataManagerCreateFileHandle(const picojson::value& args, picojson::object& out);
+ common::PlatformResult InitializeHandleIfNeeded(const std::string& uri, const int id);
void MetadataFileHandleGet(const picojson::value& args, picojson::object& out);
+ void MetadataFileHandleGetArtwork(const picojson::value& args, picojson::object& out);
void MetadataFileHandleRelease(const picojson::value& args, picojson::object& out);
std::map handles_map_;
--
2.34.1