[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 5b877c95d1fe1e4b3417c8f2f3e54e0fa8d15f9a..d89b5ad83fa093861be977af948612198382f6cf 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 ed7dc3032e24171798498da211b9bcd31c7a3326..920a9abc952401e34b6e7a7f4ff108c10bd75b05 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 e6800a9af94756b2fb42d579969af0887eebc04e..da5bb4f5da025265af5c6e1adc2d999dac484e2e 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 8734db0e190c4ea7478c50efa96a20d75cd697d1..25643baccf9b0b26524138e2020b55274e4c73d2 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