[Metadata] Implementation of get() and release() 46/237846/3
authorPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Mon, 6 Jul 2020 05:16:50 +0000 (07:16 +0200)
committerLukasz Bardeli <l.bardeli@samsung.com>
Wed, 8 Jul 2020 06:57:19 +0000 (06:57 +0000)
Implementation supports release() which frees all resources allocated
for metadata extraction.
Implementation supports get() for gathering metadata values. If get is called
after release(), API automatically recreates all handles for file.

[ACR]  https://code.sec.samsung.net/jira/browse/TWDAPI-265

[Verification] Chcecked in chrome console:
> m = tizen.metadata.createFileHandle("file:///home/owner/media/Videos/mp4video_mp3audio.mp4")
> m.get("DURATION")
> m.release()
> m.get("DURATION")
> m.get("VIDEO_WIDTH")
> m.release()

Change-Id: I2ed27a7c8009325817c32c993f5f8d4f00cd063e

src/metadata/metadata_api.js
src/metadata/metadata_file_handle.cc
src/metadata/metadata_file_handle.h
src/metadata/metadata_instance.cc

index 5b877c9..d89b5ad 100755 (executable)
@@ -21,6 +21,44 @@ var types_ = validator_.Types;
 var T_ = privUtils_.type;
 var native_ = new xwalk.utils.NativeManager(extension);
 
+var MetadataType = {
+    ALBUM: 'ALBUM',
+    ALBUM_ARTIST: 'ALBUM_ARTIST',
+    ALTITUDE: 'ALTITUDE',
+    ARTIST: 'ARTIST',
+    AUDIO_BITPERSAMPLE: 'AUDIO_BITPERSAMPLE',
+    AUDIO_BITRATE: 'AUDIO_BITRATE',
+    AUDIO_CHANNELS: 'AUDIO_CHANNELS',
+    AUDIO_CODEC: 'AUDIO_CODEC',
+    AUDIO_SAMPLERATE: 'AUDIO_SAMPLERATE',
+    CLASSIFICATION: 'CLASSIFICATION',
+    COMMENT: 'COMMENT',
+    COMPOSER: 'COMPOSER',
+    CONDUCTOR: 'CONDUCTOR',
+    COPYRIGHT: 'COPYRIGHT',
+    DATE: 'DATE',
+    DESCRIPTION: 'DESCRIPTION',
+    DURATION: 'DURATION',
+    GENRE: 'GENRE',
+    HAS_AUDIO: 'HAS_AUDIO',
+    HAS_VIDEO: 'HAS_VIDEO',
+    LATITUDE: 'LATITUDE',
+    LONGITUDE: 'LONGITUDE',
+    MODE_360: 'MODE_360',
+    RATING: 'RATING',
+    RECDATE: 'RECDATE',
+    ROTATE: 'ROTATE',
+    SYNCLYRICS_NUM: 'SYNCLYRICS_NUM',
+    TITLE: 'TITLE',
+    TRACK_NUM: 'TRACK_NUM',
+    UNSYNCLYRICS: 'UNSYNCLYRICS',
+    VIDEO_BITRATE: 'VIDEO_BITRATE',
+    VIDEO_CODEC: 'VIDEO_CODEC',
+    VIDEO_FPS: 'VIDEO_FPS',
+    VIDEO_HEIGHT: 'VIDEO_HEIGHT',
+    VIDEO_WIDTH: 'VIDEO_WIDTH'
+};
+
 function MetadataManager() {}
 
 MetadataManager.prototype.createFileHandle = function() {
@@ -54,5 +92,40 @@ function MetadataFileHandle(data) {
     });
 }
 
+MetadataFileHandle.prototype.get = function() {
+    var args = validator_.validateArgs(arguments, [
+        {
+            name: 'type',
+            type: types_.ENUM,
+            values: Object.keys(MetadataType)
+        }
+    ]);
+    var data = {
+        path: this.path,
+        id: this._id,
+        type: args.type
+    };
+
+    var result = native_.callSync('MetadataFileHandleGet', data);
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+
+    return native_.getResultObject(result);
+};
+
+MetadataFileHandle.prototype.release = function() {
+    var data = {
+        id: this._id
+    };
+
+    var result = native_.callSync('MetadataFileHandleRelease', data);
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+
+    return native_.getResultObject(result);
+};
+
 // Exports
 exports = new MetadataManager();
index ed7dc30..920a9ab 100644 (file)
@@ -17,6 +17,7 @@
 #include "metadata/metadata_file_handle.h"
 
 #include "common/logger.h"
+#include "common/platform_enum.h"
 #include "common/platform_exception.h"
 
 namespace extension {
@@ -24,6 +25,45 @@ namespace metadata {
 
 using namespace common;
 
+namespace types {
+const common::PlatformEnum<metadata_extractor_attr_e> MetadataTypeEnum{
+    {"ALBUM", METADATA_ALBUM},
+    {"ALBUM_ARTIST", METADATA_ALBUM_ARTIST},
+    {"ALTITUDE", METADATA_ALTITUDE},
+    {"ARTIST", METADATA_ARTIST},
+    {"AUDIO_BITPERSAMPLE", METADATA_AUDIO_BITPERSAMPLE},
+    {"AUDIO_BITRATE", METADATA_AUDIO_BITRATE},
+    {"AUDIO_CHANNELS", METADATA_AUDIO_CHANNELS},
+    {"AUDIO_CODEC", METADATA_AUDIO_CODEC},
+    {"AUDIO_SAMPLERATE", METADATA_AUDIO_SAMPLERATE},
+    {"CLASSIFICATION", METADATA_CLASSIFICATION},
+    {"COMMENT", METADATA_COMMENT},
+    {"COMPOSER", METADATA_COMPOSER},
+    {"CONDUCTOR", METADATA_CONDUCTOR},
+    {"COPYRIGHT", METADATA_COPYRIGHT},
+    {"DATE", METADATA_DATE},
+    {"DESCRIPTION", METADATA_DESCRIPTION},
+    {"DURATION", METADATA_DURATION},
+    {"GENRE", METADATA_GENRE},
+    {"HAS_AUDIO", METADATA_HAS_AUDIO},
+    {"HAS_VIDEO", METADATA_HAS_VIDEO},
+    {"LATITUDE", METADATA_LATITUDE},
+    {"LONGITUDE", METADATA_LONGITUDE},
+    {"MODE_360", METADATA_360},
+    {"RATING", METADATA_RATING},
+    {"RECDATE", METADATA_RECDATE},
+    {"ROTATE", METADATA_ROTATE},
+    {"SYNCLYRICS_NUM", METADATA_SYNCLYRICS_NUM},
+    {"TITLE", METADATA_TITLE},
+    {"TRACK_NUM", METADATA_TRACK_NUM},
+    {"UNSYNCLYRICS", METADATA_UNSYNCLYRICS},
+    {"VIDEO_BITRATE", METADATA_VIDEO_BITRATE},
+    {"VIDEO_CODEC", METADATA_VIDEO_CODEC},
+    {"VIDEO_FPS", METADATA_VIDEO_FPS},
+    {"VIDEO_HEIGHT", METADATA_VIDEO_HEIGHT},
+    {"VIDEO_WIDTH", METADATA_VIDEO_WIDTH}};
+}
+
 PlatformResult convertErrorCode(int err) {
   switch (err) {
     case METADATA_EXTRACTOR_ERROR_FILE_EXISTS:
@@ -98,5 +138,30 @@ picojson::value MetadataFileHandle::ToJSON() {
   return result;
 }
 
+PlatformResult MetadataFileHandle::Get(const std::string& type, std::string* result) {
+  ScopeLogger();
+
+  metadata_extractor_attr_e native_type;
+  auto res = types::MetadataTypeEnum.getValue(type, &native_type);
+  if (!res) {
+    LoggerE("MetadataTypeEnum.getValue() failed, error: %s", res.message().c_str());
+    return res;
+  }
+
+  char* value = nullptr;
+  int native_res = metadata_extractor_get_metadata(handle_, native_type, &value);
+  if (METADATA_EXTRACTOR_ERROR_NONE != native_res) {
+    LoggerE("Error during getting metadata: %d", native_res);
+    return convertErrorCode(native_res);
+  }
+  // it is possible that native function returns success, but
+  // value is null in case when metadata is missing in file, thus returning empty string then
+  if (value) {
+    *result = value;
+    free(value);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // namespace metadata
 }  // namespace extension
index e6800a9..da5bb4f 100644 (file)
@@ -36,6 +36,7 @@ class MetadataFileHandle {
   picojson::value ToJSON();
 
   common::PlatformResult Initialize(const std::string& path);
+  common::PlatformResult Get(const std::string& type, std::string* result);
 
  private:
   metadata_extractor_h handle_;
index 8734db0..25643ba 100644 (file)
@@ -88,15 +88,57 @@ void MetadataInstance::MetadataManagerCreateFileHandle(const picojson::value& ar
 
 void MetadataInstance::MetadataFileHandleGet(const picojson::value& args, picojson::object& out) {
   ScopeLogger();
+  const std::string& path = args.get("path").get<std::string>();
+  const int id = static_cast<int>(args.get("id").get<double>());
+  const std::string& type = args.get("type").get<std::string>();
+
+  LoggerD("File: %s getting metadata type: %s", path.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");
+    // re- create handle
+    auto m = MetadataFileHandle{id};
+    auto res = m.Initialize(path);
+    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;
+    }
+    // store it in the map
+    handles_map_.insert(std::pair<int, MetadataFileHandle>(id, std::move(m)));
+  }
 
-  LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Not implemented yet"), &out);
+  try {
+    MetadataFileHandle& m = handles_map_.at(id);
+    auto res = m.Get(type, &value);
+    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(picojson::value(value), out);
 }
 
 void MetadataInstance::MetadataFileHandleRelease(const picojson::value& args,
                                                  picojson::object& out) {
   ScopeLogger();
+  const int id = static_cast<int>(args.get("id").get<double>());
+
+  int erased_elems = handles_map_.erase(id);
+  LoggerD("Released %d handle for id %d", erased_elems, id);
 
-  LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Not implemented yet"), &out);
+  ReportSuccess(out);
 }
 
 }  // namespace metadata