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