From: Piotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics Date: Thu, 26 Nov 2020 08:55:11 +0000 (+0100) Subject: [Metadata] Add getSyncLyrics to MetadataHandle X-Git-Tag: submit/tizen/20201209.085808~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fc985e637d1b4f6307e094ded36d41ed6631f0b8;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Metadata] Add getSyncLyrics to MetadataHandle [ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-271 [Verification] Code compiles withotu errors. Works well for mp3 file with SYLT data. // Prectondition - file preparation (with python code) // important - SYLT need to be UTF-8 or ISO-8859 encoded to be supported on Tizen device from mutagen.id3 import ID3, SYLT, Encoding tag = ID3("sample.mp3") sync_lrc = [("TEST lyrics 1", 100), ("another TEST lyrics - 2", 2000), ("yet another TEST lyrics", 4000)] # [(lrc, millisecond), ] tag.setall("SYLT", [SYLT(encoding=Encoding.UTF8, lang='eng', format=2, type=1, text=sync_lrc)]) tag.save() tag.getall("SYLT") // then push file to device // then run below code in chrome console var path = "videos/sample.mp3"; var fileHandle = tizen.metadata.createFileHandle(path); var lyrics_num = fileHandle.get("SYNCLYRICS_NUM"); for (var i = 0; i < lyrics_num; ++i) { var lyrics = fileHandle.getSyncLyrics(i); console.log("Lyrics " + i + " (" + lyrics.timestamp + "ms): " + lyrics.lyrics); } // expected return be like console-via-logger.js:173 Lyrics 0 (100ms): TEST lyrics 1 console-via-logger.js:173 Lyrics 1 (2000ms): another TEST lyrics - 2 console-via-logger.js:173 Lyrics 2 (4000ms): yet another TEST lyrics Change-Id: I01a502f40655532a37fc4055480e35826bb7a697 --- diff --git a/src/metadata/metadata_api.js b/src/metadata/metadata_api.js index 236b758e..6126c4a2 100755 --- a/src/metadata/metadata_api.js +++ b/src/metadata/metadata_api.js @@ -195,5 +195,30 @@ MetadataFileHandle.prototype.getFrameAtTime = function() { return new Blob([encodedData]); }; +MetadataFileHandle.prototype.getSyncLyrics = function() { + var args = validator_.validateArgs(arguments, [ + { name: 'index', type: types_.UNSIGNED_LONG } + ]); + + var data = { + uri: this.uri, + id: this._id, + index: args.index + }; + + var result = native_.callSync('MetadataFileHandleGetSyncLyrics', data); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + return new MetadataSyncLyrics(native_.getResultObject(result)); +}; + +function MetadataSyncLyrics(data) { + Object.defineProperties(this, { + timestamp: { value: data.timestamp, writable: false, enumerable: true }, + lyrics: { value: data.lyrics, writable: false, enumerable: true } + }); +} + // Exports exports = new MetadataManager(); diff --git a/src/metadata/metadata_file_handle.cc b/src/metadata/metadata_file_handle.cc index b3d97613..2dfe0020 100644 --- a/src/metadata/metadata_file_handle.cc +++ b/src/metadata/metadata_file_handle.cc @@ -107,13 +107,13 @@ std::string convertUriToPath(const std::string& str) { } } -MetadataFileHandle::MetadataFileHandle(int id) : handle_(nullptr), id_(id), width_(0), height_(0) { +MetadataFileHandle::MetadataFileHandle(int id) : handle_(nullptr), id_(id), width_(0), height_(0), lyrics_num_(0) { ScopeLogger(); } // 'this' owns a handle_, and uri_ and invalidates 'o' MetadataFileHandle::MetadataFileHandle(MetadataFileHandle&& o) - : handle_(nullptr), id_(o.id_), uri_(std::move(o.uri_)), width_(0), height_(0) { + : handle_(nullptr), id_(o.id_), uri_(std::move(o.uri_)), width_(0), height_(0), lyrics_num_(0) { ScopeLogger(); handle_ = o.handle_; o.handle_ = nullptr; @@ -128,6 +128,7 @@ MetadataFileHandle& MetadataFileHandle::operator=(MetadataFileHandle&& o) { uri_ = std::move(o.uri_); width_ = o.width_; height_ = o.height_; + lyrics_num_ = o.lyrics_num_; return *this; } @@ -363,5 +364,51 @@ PlatformResult MetadataFileHandle::GetFrame(const unsigned long timestamp, const return PlatformResult(ErrorCode::NO_ERROR); } +PlatformResult MetadataFileHandle::InitSyncLyricsNum() { + ScopeLogger(); + if (0 == lyrics_num_) { + char* value = nullptr; + int native_res = metadata_extractor_get_metadata(handle_, METADATA_SYNCLYRICS_NUM, &value); + if (METADATA_EXTRACTOR_ERROR_NONE != native_res) { + LoggerE("Error during getting lyrics number: %d", native_res); + return convertErrorCode(native_res); + } + lyrics_num_ = (unsigned long)atoi(value); + free(value); + } + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult MetadataFileHandle::GetSyncLyrics(const unsigned long index, + unsigned long* timestamp, + std::string* lyrics_string) { + ScopeLogger(); + char* lyrics = nullptr; + SCOPE_EXIT { + free(lyrics); + }; + + auto ret = InitSyncLyricsNum(); + if (!ret) { + return ret; + } + + // validation of input index (available values are <0; lyrics_num -1>) + if (index >= lyrics_num_) { + std::string message = "Invalid lyrics index: " + std::to_string(index); + return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, message.c_str()); + } + + int native_res = metadata_extractor_get_synclyrics(handle_, index, timestamp, &lyrics); + if (METADATA_EXTRACTOR_ERROR_NONE != native_res) { + LoggerE("Error during getting sync lyrics: %d", native_res); + return convertErrorCode(native_res); + } + if (lyrics) { + *lyrics_string = lyrics; + } + 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 2bcd8d03..f0136b04 100644 --- a/src/metadata/metadata_file_handle.h +++ b/src/metadata/metadata_file_handle.h @@ -42,9 +42,12 @@ class MetadataFileHandle { common::PlatformResult GetFrame(std::vector* frame_array); common::PlatformResult GetFrame(const unsigned long timestamp, const bool is_accurate, std::vector* frame_array); + common::PlatformResult GetSyncLyrics(const unsigned long index, unsigned long* timestamp, + std::string* lyrics_string); private: common::PlatformResult InitWidthHeight(); + common::PlatformResult InitSyncLyricsNum(); common::PlatformResult EncodeJPEG(unsigned char* frame, size_t frame_size, std::uint8_t** uint8_frame, size_t* buffer_size); @@ -54,6 +57,7 @@ class MetadataFileHandle { unsigned int width_; unsigned int height_; + unsigned int lyrics_num_; }; } // namespace metadata diff --git a/src/metadata/metadata_instance.cc b/src/metadata/metadata_instance.cc index 49e1cd62..eb8c02eb 100644 --- a/src/metadata/metadata_instance.cc +++ b/src/metadata/metadata_instance.cc @@ -37,6 +37,7 @@ MetadataInstance::MetadataInstance() : next_handle_id_(1) { REGISTER_METHOD(MetadataFileHandleGetArtwork); REGISTER_METHOD(MetadataFileHandleGetThumbnailFrame); REGISTER_METHOD(MetadataFileHandleGetFrameAtTime); + REGISTER_METHOD(MetadataFileHandleGetSyncLyrics); REGISTER_METHOD(MetadataFileHandleRelease); #undef REGISTER_METHOD } @@ -242,6 +243,49 @@ void MetadataInstance::MetadataFileHandleGetFrameAtTime(const picojson::value& a ReportSuccess(picojson::value(result_frame), out); } +picojson::value getSyncLyricsJSON(const unsigned long timestamp, const std::string& lyrics) { + ScopeLogger(); + picojson::value result = picojson::value(picojson::object()); + picojson::object& result_obj = result.get(); + result_obj.insert(std::make_pair("timestamp", picojson::value((double)timestamp))); + result_obj.insert(std::make_pair("lyrics", picojson::value(lyrics))); + + return result; +} + +void MetadataInstance::MetadataFileHandleGetSyncLyrics(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 unsigned long index = static_cast(args.get("index").get()); + + auto res = InitializeHandleIfNeeded(uri, id); + if (!res) { + LogAndReportError(res, &out); + return; + } + + unsigned long timestamp = 0; + std::string lyrics; + try { + MetadataFileHandle& m = handles_map_.at(id); + + auto res = m.GetSyncLyrics(index, ×tamp, &lyrics); + if (!res) { + LogAndReportError(res, &out); + return; + } + } catch (...) { + // this should never happen + LogAndReportError( + PlatformResult(ErrorCode::ABORT_ERR, "Unknown error during accessing a file."), &out); + return; + } + + ReportSuccess(getSyncLyricsJSON(timestamp, lyrics), 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 26a3f499..61dd760b 100644 --- a/src/metadata/metadata_instance.h +++ b/src/metadata/metadata_instance.h @@ -35,6 +35,7 @@ class MetadataInstance : public common::ParsedInstance { void MetadataFileHandleGetArtwork(const picojson::value& args, picojson::object& out); void MetadataFileHandleGetThumbnailFrame(const picojson::value& args, picojson::object& out); void MetadataFileHandleGetFrameAtTime(const picojson::value& args, picojson::object& out); + void MetadataFileHandleGetSyncLyrics(const picojson::value& args, picojson::object& out); void MetadataFileHandleRelease(const picojson::value& args, picojson::object& out); std::map handles_map_;