Use FileRef instead 53/276953/9
authorminje.ahn <minje.ahn@samsung.com>
Tue, 28 Jun 2022 08:41:53 +0000 (17:41 +0900)
committerminje.ahn <minje.ahn@samsung.com>
Wed, 29 Jun 2022 07:49:01 +0000 (16:49 +0900)
FileRef helps to respond appropriately according to each format.

Change-Id: Id2af3ca82e99c40b0dd6853c32f41c526c872e97
Signed-off-by: minje.ahn <minje.ahn@samsung.com>
include/metadata_editor_private.h
src/metadata_editor.cpp

index fba0ffd..105a677 100755 (executable)
@@ -60,14 +60,14 @@ extern "C" {
        } while (0)
 
 #define metadata_editor_retvm_if(expr, val, fmt, arg...) do { \
-                       if (expr) { \
-                               LOGE(FONT_COLOR_RED"" fmt "" FONT_COLOR_RESET, ##arg);  \
+                       if ((expr)) { \
+                               LOGE(FONT_COLOR_RED"" fmt "" FONT_COLOR_RESET, ##arg); \
                                return (val); \
                        } \
                } while (0)
 
 #define metadata_editor_retm_if(expr, fmt, arg...) do { \
-                       if (expr) { \
+                       if ((expr)) { \
                                LOGE(FONT_COLOR_RED"" fmt "" FONT_COLOR_RESET, ##arg); \
                                return; \
                        } \
index 62dfcd5..c2d1612 100755 (executable)
@@ -24,6 +24,8 @@
 #include <glib.h>
 
 #include <taglib/tag.h>
+#include <taglib/fileref.h>
+#include <taglib/tpropertymap.h>
 #include <taglib/mpegfile.h>
 #include <taglib/mp4file.h>
 #include <taglib/flacfile.h>
@@ -46,138 +48,7 @@ using namespace TagLib;
 
 #define MIME_TYPE_JPEG "image/jpeg"
 #define MIME_TYPE_PNG "image/png"
-
-class MetadataFile
-{
-public:
-       virtual ~MetadataFile() = default;
-
-       virtual int appendPicture(const char *picture ,size_t size, const char *mime_type) = 0;
-       virtual int getPicture(int index, void **picture, int *size, char **mime_type) = 0;
-       virtual int removePicture(int index) = 0;
-
-       virtual int setMetadata(metadata_editor_attr_e attribute, const char *value) = 0;
-       virtual int getMetadata(metadata_editor_attr_e attribute, char **value) = 0;
-       virtual int updateMetadata() = 0;
-
-       bool isOpen() { return file->isOpen(); }
-       bool readOnly() { return file->readOnly(); }
-
-protected:
-       File* file {};
-};
-
-class Mp3MetadataFile : public MetadataFile {
-public:
-       explicit Mp3MetadataFile(const char *path) {
-               file = new MPEG::File(path);
-       }
-
-       ~Mp3MetadataFile() override {
-               delete dynamic_cast<TagLib::MPEG::File*>(file);
-       }
-
-       int appendPicture(const char *picture ,size_t size, const char *mime_type) override;
-       int getPicture(int index, void **picture, int *size, char **mime_type) override;
-       int removePicture(int index) override;
-       int setMetadata(metadata_editor_attr_e attribute, const char *value) override;
-       int getMetadata(metadata_editor_attr_e attribute, char **value) override;
-       int updateMetadata() override;
-};
-
-class Mp4MetadataFile : public MetadataFile
-{
-public:
-       explicit Mp4MetadataFile(const char *path) {
-               file = new MP4::File(path);
-       }
-       ~Mp4MetadataFile() override {
-               delete dynamic_cast<TagLib::MP4::File*>(file);
-       }
-
-       int appendPicture(const char *picture ,size_t size, const char *mime_type) override;
-       int getPicture(int index, void **picture, int *size, char **mime_type) override;
-       int removePicture(int index) override;
-       int setMetadata(metadata_editor_attr_e attribute, const char *value) override;
-       int getMetadata(metadata_editor_attr_e attribute, char **value) override;
-       int updateMetadata() override;
-};
-
-class FlacMetadataFile : public MetadataFile
-{
-public:
-       explicit FlacMetadataFile(const char *path) {
-               file = new FLAC::File(path);
-       }
-       ~FlacMetadataFile() override {
-               delete dynamic_cast<TagLib::FLAC::File*>(file);
-       }
-
-       int appendPicture(const char *picture ,size_t size, const char *mime_type) override;
-       int getPicture(int index, void **picture, int *size, char **mime_type) override;
-       int removePicture(int index) override;
-       int setMetadata(metadata_editor_attr_e attribute, const char *value) override;
-       int getMetadata(metadata_editor_attr_e attribute, char **value) override;
-       int updateMetadata() override;
-};
-
-class OggVorbisMetadataFile : public MetadataFile
-{
-public:
-       explicit OggVorbisMetadataFile(const char *path) {
-               file = new Ogg::Vorbis::File(path);
-       }
-       ~OggVorbisMetadataFile() override {
-               delete dynamic_cast<TagLib::Ogg::Vorbis::File*>(file);
-       }
-
-       int appendPicture(const char *picture ,size_t size, const char *mime_type) override;
-       int getPicture(int index, void **picture, int *size, char **mime_type) override;
-       int removePicture(int index) override;
-       int setMetadata(metadata_editor_attr_e attribute, const char *value) override;
-       int getMetadata(metadata_editor_attr_e attribute, char **value) override;
-       int updateMetadata() override;
-};
-
-class OggFlacMetadataFile : public MetadataFile
-{
-public:
-       explicit OggFlacMetadataFile(const char *path) {
-               file = new Ogg::FLAC::File(path);
-       }
-       ~OggFlacMetadataFile() override {
-               delete dynamic_cast<TagLib::Ogg::FLAC::File*>(file);
-       }
-
-       int appendPicture(const char *picture ,size_t size, const char *mime_type) override;
-       int getPicture(int index, void **picture, int *size, char **mime_type) override;
-       int removePicture(int index) override;
-       int setMetadata(metadata_editor_attr_e attribute, const char *value) override;
-       int getMetadata(metadata_editor_attr_e attribute, char **value) override;
-       int updateMetadata() override;
-};
-
-class WavMetadataFile : public MetadataFile
-{
-public:
-       explicit WavMetadataFile(const char *path) {
-               file = new RIFF::WAV::File(path);
-       }
-       ~WavMetadataFile() override {
-               delete dynamic_cast<TagLib::RIFF::WAV::File*>(file);
-       }
-
-       int appendPicture(const char *picture ,size_t size, const char *mime_type) override;
-       int getPicture(int index, void **picture, int *size, char **mime_type) override;
-       int removePicture(int index) override;
-       int setMetadata(metadata_editor_attr_e attribute, const char *value) override;
-       int getMetadata(metadata_editor_attr_e attribute, char **value) override;
-       int updateMetadata() override;
-};
-
-typedef struct {
-       MetadataFile* intf;
-} metadata_editor_s;
+#define EXT_LEN 255
 
 typedef enum {
        METADATA_EDITOR_FORMAT_MP3 = 0,                 /**< MP3 File */
@@ -189,416 +60,40 @@ typedef enum {
        METADATA_EDITOR_FORMAT_NOTYPE = 0xFF            /**< Error type. File type is not correct or not specified */
 } metadata_editor_format_e;
 
-static int __check_metadata_parameter(metadata_editor_s *metadata)
-{
-       metadata_editor_retvm_if(!metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-       metadata_editor_retvm_if(!metadata->intf, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __check_metadata_set_parameter(metadata_editor_s *metadata)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_parameter(metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_parameter");
-
-       metadata_editor_retvm_if(metadata->intf->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "File is readonly. Unable to modify");
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __check_metadata_get_parameter(metadata_editor_s *metadata, char **value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_parameter(metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_parameter");
-
-       metadata_editor_retvm_if(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __ID3_getTwixFrameByName(ID3v1::Tag *tag1, ID3v2::Tag *tag2, const char *frameID, char **value)
-{
-       metadata_editor_retvm_if(!frameID, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid frameID");
-
-       if (tag2 && !(tag2->frameListMap()[frameID].isEmpty())) {
-               metadata_editor_info("The frame %s exists in ID3v2 tag", frameID);
-               *value = g_strdup(tag2->frameListMap()[frameID][0]->toString().toCString(true));
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-
-       metadata_editor_info("The frame %s in ID3v2 tag is empty", frameID);
-
-       if (!tag1 || tag1->isEmpty()) {
-               metadata_editor_info("The frame %s in ID3v1 tag is empty as well", frameID);
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-
-       metadata_editor_info("Reading data from ID3v1 tag");
-
-       //check isEmpty(). toCString() returns "", when String is NULL.
-       //for "genre", taglib returns "", if genre is out or range.
-       if (!strcmp(frameID, "TPE1") && !(tag1->artist().isEmpty()))    /* artist */
-               *value = g_strdup(tag1->artist().toCString(true));
-       else if (!strcmp(frameID, "TALB") && !(tag1->album().isEmpty()))        /* album */
-               *value = g_strdup(tag1->album().toCString(true));
-       else if (!strcmp(frameID, "COMM") && !(tag1->comment().isEmpty()))      /* comment */
-               *value = g_strdup(tag1->comment().toCString(true));
-       else if (!strcmp(frameID, "TCON") && !(tag1->genre().isEmpty()) && !(tag1->genre().isEmpty()))  /* genre */
-               *value = g_strdup(tag1->genre().toCString(true));
-       else if (!strcmp(frameID, "TIT2") && !(tag1->title().isEmpty()))        /* title */
-               *value = g_strdup(tag1->title().toCString(true));
-       else if (!strcmp(frameID, "TRCK"))      /* track */
-               *value = g_strdup_printf("%u", tag1->track());
-       else if (!strcmp(frameID, "TDRC"))      /* data (year) */
-               *value = g_strdup_printf("%u", tag1->year());
-       else
-               metadata_editor_debug("The desired frame was not found");
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static void __ID3v1_setFrameByName(ID3v1::Tag *tag1, const char *frameID, const char *value)
-{
-       metadata_editor_retm_if(!tag1, "[No-Error] No ID3v1 tag to update");    //ID3v1 is optional
-       metadata_editor_retm_if(tag1->isEmpty(), "[No-Error] ID3v1 tag is empty");
-
-       if (!value || (*value == '\0')) {
-               metadata_editor_info("Request for frame %s deletion", frameID);
-
-               if (!strcmp(frameID, "TPE1"))
-                       tag1->setArtist("");
-               else if (!strcmp(frameID, "TALB"))
-                       tag1->setAlbum("");
-               else if (!strcmp(frameID, "TCON"))
-                       tag1->setGenre("");
-               else if (!strcmp(frameID, "TIT2"))
-                       tag1->setTitle("");
-               else if (!strcmp(frameID, "TRCK"))
-                       tag1->setTrack(0);
-               else if (!strcmp(frameID, "TDRC"))
-                       tag1->setYear(0);
-
-               return;
-       }
-
-       if (!strcmp(frameID, "TPE1"))
-               tag1->setArtist(value);
-       else if (!strcmp(frameID, "TALB"))
-               tag1->setAlbum(value);
-       else if (!strcmp(frameID, "TCON"))              // Genre in ID3v1 is enumeration, so can not write it with "value"
-               tag1->setGenre("");
-       else if (!strcmp(frameID, "TIT2"))
-               tag1->setTitle(value);
-       else if (!strcmp(frameID, "TRCK"))
-               tag1->setTrack(atoi(value));
-       else if (!strcmp(frameID, "TDRC"))
-               tag1->setYear(atoi(value));
-
-       return;
-}
-
-static int __ID3v2_setFrameByName(ID3v2::Tag *tag2, const char *frameID, const char *value)
-{
-       metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
-       metadata_editor_retvm_if(!frameID, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid frameID");
-
-       // If the pointer is NULL or c-string is empty - handle as request for deletion
-       if (!value || (*value == '\0')) {
-               metadata_editor_info("Request for frame %s deletion", frameID);
-               tag2->removeFrames(frameID);
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-
-       // Check if the ID3v2 tag exists
-       if (tag2->frameListMap()[frameID].isEmpty()) {
-               metadata_editor_info("The frame %s does not exist. Creating", frameID);
-               // This is a common frame type for textural frames except comment frame
-               auto fr = new ID3v2::TextIdentificationFrame(frameID);
-
-               fr->setTextEncoding(String::UTF8);
-               fr->setText(String(value, String::UTF8));
-               tag2->addFrame(fr);
-       } else {                // if not - just modify the data in the existing frame
-               metadata_editor_info("The frame %s exists. Changing", frameID);
-               tag2->frameListMap()[frameID][0]->setText(String(value, String::UTF8));
-       }
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __ID3_setTwixFrameByName(ID3v1::Tag *tag1, ID3v2::Tag *tag2, const char *frameID, const char *value)
-{
-       metadata_editor_retvm_if(!frameID, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid frameID");
-       if (tag1 && !(tag1->isEmpty()))
-               __ID3v1_setFrameByName(tag1, frameID, value);
-
-       return __ID3v2_setFrameByName(tag2, frameID, value);
-}
-
-static int __ID3_getNumberOfPictures(ID3v2::Tag *tag2, char **value)
-{
-       metadata_editor_retvm_if(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
-
-       *value = g_strdup_printf("%u", tag2 ? tag2->frameListMap()["APIC"].size() : 0);
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __ID3_getLyricsFrame(ID3v2::Tag *tag2, char **value)
-{
-       metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_NONE, "[No-Error] No tag");
-
-       auto lst = tag2->frameListMap()["USLT"];                // link to unsynchronized lyric frames in tag
-       metadata_editor_retvm_if(lst.isEmpty(), METADATA_EDITOR_ERROR_NONE, "The frame USLT does not exist");
-
-       metadata_editor_info("The frame USLT exists");
-       auto it = lst.begin();
-       auto frame = static_cast<ID3v2::UnsynchronizedLyricsFrame*>(*it);
-
-       if (!(frame->text().isEmpty()))
-               *value = g_strdup(frame->text().toCString(true));
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __ID3_setTwixCommentFrame(ID3v1::Tag *tag1, ID3v2::Tag *tag2, const char *value)
-{
-       metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
-
-       // If the pointer is NULL or c-string is empty - handle as request for deletion
-       if (!value || (*value == '\0')) {
-               metadata_editor_info("Request for frame COMM deletion");
-               tag2->removeFrames("COMM");
-               if (tag1 && !tag1->isEmpty())
-                       tag1->setComment("");
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-       // If the comment frame is empty - create the frame and add it to the list
-       if (tag2->frameListMap()["COMM"].isEmpty()) {
-               metadata_editor_info("The frame COMM does not exist. Creating");
-               auto fr = new ID3v2::CommentsFrame;
-
-               fr->setText(String(value, String::UTF8));
-               fr->setTextEncoding(String::UTF8);
-               tag2->addFrame(fr);
-       } else {                                                // If the frame already exists - just modify its value
-               metadata_editor_info("The frame COMM exists. Changing");
-               tag2->frameListMap()["COMM"][0]->setText(String(value, String::UTF8));
-       }
-
-       if (tag1 && !tag1->isEmpty()) {                 // Copy the value to ID3v1 tag comment
-               metadata_editor_info("ID3v1 tag also exists. Copying frame");
-               tag1->setComment(value);
-       }
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __ID3_setLyricsFrame(ID3v2::Tag *tag2, const char *value)
-{
-       metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Error. ID3v2 tag was not created. Can not proceed metadata updating");
-
-       auto lst = tag2->frameListMap()["USLT"];        // link to unsynchronized lyric frames in tag
-       // If the pointer is NULL or c-string is empty - handle as request for deletion
-       if (!value || (*value == '\0')) {
-               metadata_editor_info("Request for frame USLT deletion");
-               tag2->removeFrames("USLT");
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-       // Check if lyrics frames exist
-       if (lst.isEmpty()) {
-               // No lyrics - create the frame and add it to the ID3v2 tag
-               metadata_editor_info("The frame USLT does not exist. Creating");
-               auto frame = new ID3v2::UnsynchronizedLyricsFrame;
-
-               frame->setTextEncoding(String::UTF8);
-               frame->setText(String(value, String::UTF8));
-               tag2->addFrame(frame);
-       } else {                                                                        // the lyrics frames exist - change the existing one
-               metadata_editor_info("USLT frames exist in file. Changing");
-               auto it = lst.begin();
-               auto frame = static_cast<ID3v2::UnsynchronizedLyricsFrame*>(*it);
-               frame->setTextEncoding(String::UTF8);
-               frame->setText(String(value, String::UTF8));
-       }
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __MP4_getStringItem(MP4::Tag *tag, const char *itemname, char **value)
-{
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_NONE, "[No-Error] No tag");
-       metadata_editor_retvm_if(!itemname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid  itemname");
-
-       auto item = tag->item(itemname);
-
-       if (item.isValid())
-               *value = g_strdup(item.toStringList().toString().toCString(false));
-       else
-               metadata_editor_info("No item <%s> in file", itemname);
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __MP4_getIntegerItem(MP4::Tag *tag, const char *itemname, char **value)
-{
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_NONE, "[No-Error] No tag");
-       metadata_editor_retvm_if(!itemname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid itemname");
-
-       auto item = tag->item(itemname);
-
-       if (item.isValid())
-               *value = g_strdup_printf("%u", item.toInt());
-       else
-               metadata_editor_info("No item <%s> in file", itemname);
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __MP4_updateStringItem(MP4::Tag *tag, const char *itemname, const char *value)
-{
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
-       metadata_editor_retvm_if(!itemname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid itemname");
-
-       // Check if it is a request for deletion
-       if ((value == NULL) || value[0] == '\0') {
-               metadata_editor_info("Request for deleting of item <%s>", itemname);
-               tag->removeItem(itemname);
-
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-       metadata_editor_info("The item <%s> will be added", itemname);
-       tag->setItem(itemname, MP4::Item(String(value, String::UTF8)));
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __MP4_updateIntegerItem(MP4::Tag *tag, const char *itemname, const char *value)
-{
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
-       metadata_editor_retvm_if(!itemname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid itemname");
-
-       // Check if it is a request for deletion
-       if ((value == NULL) || value[0] == '\0') {
-               metadata_editor_info("Request for deleting of item <%s>", itemname);
-               tag->removeItem(itemname);
-
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-       // Check if the value is integer string then it can be successfully converted into integer
-       if (isdigit(value[0])) {
-               metadata_editor_info("The item <%s> will be added", itemname);
-               int number = atoi(value);
-               tag->setItem(itemname, MP4::Item(number));
-               return METADATA_EDITOR_ERROR_NONE;
-       } else {                                                                                // Notify that string is not a number to process
-               metadata_editor_error("Error. String does not contain a number");
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-}
-
-static int __MP4_getNumberOfPictures(MP4::Tag *tag, char **value)
-{
-       metadata_editor_retvm_if(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
-
-       if (tag && tag->contains("covr"))
-               *value = g_strdup_printf("%u", tag->item("covr").toCoverArtList().size());
-       else
-               *value = g_strdup_printf("0");
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __xiph_getFieldValue(Ogg::XiphComment *xtag, const char *fieldname, char **value)
-{
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_NONE, "[No-Error] No tag");
-       metadata_editor_retvm_if(!fieldname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid fieldname");
-
-       auto &fieldMap = xtag->fieldListMap();
-       auto it = fieldMap.find(fieldname);
-
-       if ((xtag->contains(fieldname)) && (it != fieldMap.end()))
-               *value = g_strdup(it->second[0].toCString(true));
-       else
-               metadata_editor_info("No field %s in Xiph Comment", fieldname);
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __xiph_updateFieldValue(Ogg::XiphComment *xtag, const char *fieldname, const char *value)
-{
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
-       metadata_editor_retvm_if(!fieldname, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid fieldname");
-
-       // Check if it is a request for deletion
-       if ((value == NULL) || value[0] == '\0') {
-               metadata_editor_info("Request for deleting of field %s", fieldname);
-               xtag->removeFields(fieldname);
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-       metadata_editor_info("The field %s will be added", fieldname);
-       // "true" is used to remove other strings of the same "fieldname" first
-       xtag->addField(fieldname, String(value, String::UTF8), true);
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __FLAC_getNumberOfPictures(FLAC::File *file, char **value)
-{
-       if (file)
-               *value = g_strdup_printf("%u", file->pictureList().size());
-       else
-               *value = g_strdup("0");
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __OGG_getNumberOfPictures(Ogg::XiphComment *xtag, char **value)
-{
-       if (xtag)
-               *value = g_strdup_printf("%u", xtag->pictureList().size());
-       else
-               *value = g_strdup("0");
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
+typedef struct {
+       FileRef *fref;
+       metadata_editor_format_e format;
+} metadata_editor_s;
 
-static int __metadata_editor_get_file_ext(const char *file_path, char *file_ext, int max_len)
+static bool __metadata_editor_get_file_ext(const char *file_path, char *file_ext, int max_len)
 {
-       int i = 0;
+       unsigned int i = 0;
        unsigned int path_len = strlen(file_path);
 
-       for (i = (int)path_len; i >= 0; i--) {
-               if ((file_path[i] == '.') && (i < (int)path_len)) {
+       for (i = path_len; i > 0; i--) {
+               if ((file_path[i] == '.') && (i < path_len)) {
                        strncpy(file_ext, &file_path[i + 1], max_len);
-                       return 0;
+                       return true;
                }
 
                /* meet the dir. no ext */
                if (file_path[i] == '/')
-                       return -1;
+                       return false;
        }
 
-       return -1;
+       return false;
 }
 
-static int __metadata_editor_get_file_type(const char *path)
+static metadata_editor_format_e __metadata_editor_get_file_type(const char *path)
 {
-       int ret = 0;
-       char mimetype[255] = {0, };
+       char mimetype[EXT_LEN] = {0, };
+       char ext[EXT_LEN] = { 0 };
 
        /* get content type and mime type from file. */
-       ret = aul_get_mime_from_file(path, mimetype, sizeof(mimetype));
-       if (ret < 0) {
+       if (aul_get_mime_from_file(path, mimetype, sizeof(mimetype)) < 0) {
                metadata_editor_debug("aul_get_mime_from_file fail.. Now trying to get type by extension");
 
-               char ext[255] = { 0 };
-               int ret = __metadata_editor_get_file_ext(path, ext, sizeof(ext));
-               metadata_editor_retvm_if(ret < 0, METADATA_EDITOR_FORMAT_NOTYPE, "__metadata_editor_get_file_ext failed");
+               metadata_editor_retvm_if(!__metadata_editor_get_file_ext(path, ext, EXT_LEN), METADATA_EDITOR_FORMAT_NOTYPE, "__metadata_editor_get_file_ext failed");
 
                if (strcasecmp(ext, "MP3") == 0)
                        return METADATA_EDITOR_FORMAT_MP3;
@@ -608,7 +103,7 @@ static int __metadata_editor_get_file_type(const char *path)
                        return METADATA_EDITOR_FORMAT_FLAC;
                else if (strcasecmp(ext, "WAV") == 0)
                        return METADATA_EDITOR_FORMAT_WAV;
-               else if (strcasecmp(ext, "OGG") == 0)   //Fix Me!flac_ogg is unusual. So if file extention of ogg is considered vorbis ogg
+               else if (strcasecmp(ext, "OGG") == 0)
                        return METADATA_EDITOR_FORMAT_OGG_VORBIS;
                else
                        return METADATA_EDITOR_FORMAT_NOTYPE;
@@ -636,15 +131,14 @@ static int __metadata_editor_get_file_type(const char *path)
 static int __metadata_editor_get_picture_type(const char *path, char **type)
 {
        int ret = 0;
-       char mimetype[255] = {0, };
+       char mimetype[EXT_LEN] = {0, };
+       char ext[EXT_LEN] = {0, };
 
        /* get content type and mime type from file. */
-       ret = aul_get_mime_from_file(path, mimetype, sizeof(mimetype));
-       if (ret < 0) {
+       if (aul_get_mime_from_file(path, mimetype, sizeof(mimetype)) < 0) {
                metadata_editor_debug("aul_get_mime_from_file fail.. Now trying to get type by extension");
 
-               char ext[255] = { 0 };
-               int ret = __metadata_editor_get_file_ext(path, ext, sizeof(ext));
+               ret = __metadata_editor_get_file_ext(path, ext, EXT_LEN);
                metadata_editor_retvm_if(ret < 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "__metadata_editor_get_file_ext failed");
 
                if (strcasecmp(ext, "JPG") == 0 || strcasecmp(ext, "JPEG") == 0) {
@@ -700,12 +194,9 @@ static int __metadata_editor_get_picture_info(const char *path, char **picture,
        return ret;
 }
 
-
-
 static int __check_file_validity(const char *path)
 {
        metadata_editor_retvm_if(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
-
        metadata_editor_sec_debug("path : [%s]", path);
 
        if (access(path, R_OK) < 0) {
@@ -721,97 +212,6 @@ static int __check_file_validity(const char *path)
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-
-static int __get_ID3_tag(metadata_editor_attr_e attribute, ID3v1::Tag *tag1, ID3v2::Tag *tag2, char **value)
-{
-       switch (attribute) {
-               case METADATA_EDITOR_ATTR_ARTIST:                       return __ID3_getTwixFrameByName(tag1, tag2, "TPE1", value);
-               case METADATA_EDITOR_ATTR_TITLE:                        return __ID3_getTwixFrameByName(tag1, tag2, "TIT2", value);
-               case METADATA_EDITOR_ATTR_ALBUM:                        return __ID3_getTwixFrameByName(tag1, tag2, "TALB", value);
-               case METADATA_EDITOR_ATTR_GENRE:                        return __ID3_getTwixFrameByName(tag1, tag2, "TCON", value);
-               case METADATA_EDITOR_ATTR_AUTHOR:                       return __ID3_getTwixFrameByName(NULL, tag2, "TCOM", value);
-               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __ID3_getTwixFrameByName(NULL, tag2, "TCOP", value);
-               case METADATA_EDITOR_ATTR_DATE:                 return __ID3_getTwixFrameByName(tag1, tag2, "TDRC", value);
-               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3_getTwixFrameByName(NULL, tag2, "TIT3", value);
-               case METADATA_EDITOR_ATTR_COMMENT:                      return __ID3_getTwixFrameByName(tag1, tag2, "COMM", value);
-               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __ID3_getTwixFrameByName(tag1, tag2, "TRCK", value);
-               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __ID3_getTwixFrameByName(NULL, tag2, "TPE3", value);
-               case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __ID3_getNumberOfPictures(tag2, value);
-               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __ID3_getLyricsFrame(tag2, value);
-               default:
-                       metadata_editor_error("Invalid attribute [%d]", attribute);
-                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-}
-
-static int __get_ogg_metadata(Ogg::XiphComment *xtag, metadata_editor_attr_e attribute, char **value)
-{
-       switch (attribute) {
-       case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_getFieldValue(xtag, "ARTIST", value);
-       case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_getFieldValue(xtag, "TITLE", value);
-       case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_getFieldValue(xtag, "ALBUM", value);
-       case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_getFieldValue(xtag, "GENRE", value);
-       case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_getFieldValue(xtag, "COMPOSER", value);
-       case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_getFieldValue(xtag, "COPYRIGHT", value);
-       case METADATA_EDITOR_ATTR_DATE:                 return __xiph_getFieldValue(xtag, "DATE", value);
-       case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_getFieldValue(xtag, "DESCRIPTION", value);
-       case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_getFieldValue(xtag, "COMMENT", value);
-       case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_getFieldValue(xtag, "TRACKNUMBER", value);
-       case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_getFieldValue(xtag, "CONDUCTOR", value);
-       case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_getFieldValue(xtag, "LYRICS", value);
-       case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __OGG_getNumberOfPictures(xtag, value);
-       default:
-               metadata_editor_error("Invalid attribute [%d]", attribute);
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-}
-
-static int __set_ID3_tag(metadata_editor_attr_e attribute, ID3v1::Tag *tag1, ID3v2::Tag *tag2, const char *value)
-{
-       metadata_editor_retvm_if(!tag2, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
-
-       switch (attribute) {
-               case METADATA_EDITOR_ATTR_ARTIST:                       return __ID3_setTwixFrameByName(tag1, tag2, "TPE1", value);
-               case METADATA_EDITOR_ATTR_TITLE:                        return __ID3_setTwixFrameByName(tag1, tag2, "TIT2", value);
-               case METADATA_EDITOR_ATTR_ALBUM:                        return __ID3_setTwixFrameByName(tag1, tag2, "TALB", value);
-               case METADATA_EDITOR_ATTR_GENRE:                        return __ID3_setTwixFrameByName(tag1, tag2, "TCON", value);
-               case METADATA_EDITOR_ATTR_AUTHOR:                       return __ID3v2_setFrameByName(tag2, "TCOM", value);
-               case METADATA_EDITOR_ATTR_COPYRIGHT:            return __ID3v2_setFrameByName(tag2, "TCOP", value);
-               case METADATA_EDITOR_ATTR_DATE:                 return __ID3_setTwixFrameByName(tag1, tag2, "TDRC", value);
-               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __ID3v2_setFrameByName(tag2, "TIT3", value);
-               case METADATA_EDITOR_ATTR_TRACK_NUM:            return __ID3_setTwixFrameByName(tag1, tag2, "TRCK", value);
-               case METADATA_EDITOR_ATTR_CONDUCTOR:            return __ID3v2_setFrameByName(tag2, "TPE3", value);
-               case METADATA_EDITOR_ATTR_COMMENT:              return __ID3_setTwixCommentFrame(tag1, tag2, value);
-               case METADATA_EDITOR_ATTR_UNSYNCLYRICS: return __ID3_setLyricsFrame(tag2, value);
-               default:
-                       metadata_editor_error("Invalid attribute [%d]", attribute);
-                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-static int __set_ogg_metadata(Ogg::XiphComment *xtag, metadata_editor_attr_e attribute, const char *value)
-{
-       switch (attribute) {
-       case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_updateFieldValue(xtag, "ARTIST", value);
-       case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_updateFieldValue(xtag, "TITLE", value);
-       case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_updateFieldValue(xtag, "ALBUM", value);
-       case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_updateFieldValue(xtag, "GENRE", value);
-       case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_updateFieldValue(xtag, "COMPOSER", value);
-       case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_updateFieldValue(xtag, "COPYRIGHT", value);
-       case METADATA_EDITOR_ATTR_DATE:                 return __xiph_updateFieldValue(xtag, "DATE", value);
-       case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_updateFieldValue(xtag, "DESCRIPTION", value);
-       case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_updateFieldValue(xtag, "COMMENT", value);
-       case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_updateFieldValue(xtag, "TRACKNUMBER", value);
-       case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_updateFieldValue(xtag, "CONDUCTOR", value);
-       case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_updateFieldValue(xtag, "LYRICS", value);
-       default:
-               metadata_editor_error("Invalid attribute [%d]", attribute);
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-}
-
 static char * __get_mime_type(const String& mime_type)
 {
        if (mime_type == MIME_TYPE_JPEG || mime_type == MIME_TYPE_PNG)
@@ -834,29 +234,19 @@ static int __is_valid_picture_index(bool is_empty, unsigned int list_size, int i
 {
        metadata_editor_debug("list size [%d] picture index[%d]", list_size, index);
 
-       if (is_empty) {
-               metadata_editor_error("No pictures in file");
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-
-       if ((index < 0) || (list_size <= (uint)index)) {
-               metadata_editor_error("Index of picture is out of range");
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
+       metadata_editor_retvm_if(is_empty, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "No picture");
+       metadata_editor_retvm_if((index < 0) || (list_size <= (uint)index), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Out of range");
 
        return METADATA_EDITOR_ERROR_NONE;
 }
 
 static int __get_APIC(ID3v2::Tag *tag, int index, void **picture, int *size, char **mime_type)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
        metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
 
        auto lst = tag->frameListMap()["APIC"];
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+       metadata_editor_retvm_if(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
 
        auto pictureFrame = static_cast<ID3v2::AttachedPictureFrame*>(lst[index]);
 
@@ -872,14 +262,11 @@ static int __get_APIC(ID3v2::Tag *tag, int index, void **picture, int *size, cha
 
 static int __get_ogg_picture(Ogg::XiphComment *xtag, int index, void **picture, int *size, char **mime_type)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
+       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid XiphComment");
 
        auto lst = xtag->pictureList();
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+       metadata_editor_retvm_if(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
 
        auto pictureFrame = static_cast<FLAC::Picture*>(lst[index]);
 
@@ -895,7 +282,7 @@ static int __get_ogg_picture(Ogg::XiphComment *xtag, int index, void **picture,
 
 static int __append_APIC(ID3v2::Tag *tag, const char *picture, size_t size, const char *mime_type)
 {
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
+       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Invalid ID3v2");
 
        auto pictureFrame = new ID3v2::AttachedPictureFrame();
 
@@ -913,7 +300,7 @@ static int __append_APIC(ID3v2::Tag *tag, const char *picture, size_t size, cons
 
 static int __append_ogg_picture(Ogg::XiphComment *xtag, const char *picture, size_t size, const char *mime_type)
 {
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
+       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Invalid XiphComment");
 
        auto frontCover = new FLAC::Picture;
 
@@ -928,14 +315,11 @@ static int __append_ogg_picture(Ogg::XiphComment *xtag, const char *picture, siz
 
 static int __remove_APIC(ID3v2::Tag *tag, int index)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
+       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid ID3v2");
 
        auto lst = tag->frameListMap()["APIC"];
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+       metadata_editor_retvm_if(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
 
        tag->removeFrame(lst[index]);
 
@@ -944,14 +328,11 @@ static int __remove_APIC(ID3v2::Tag *tag, int index)
 
 static int __remove_ogg_picture(Ogg::XiphComment *xtag, int index)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
+       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid XiphComment");
 
        auto lst = xtag->pictureList();
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+       metadata_editor_retvm_if(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
 
        TagLib::List<TagLib::FLAC::Picture*>::Iterator it = lst.begin();
        std::advance(it, index);
@@ -960,463 +341,306 @@ static int __remove_ogg_picture(Ogg::XiphComment *xtag, int index)
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-
-int Mp3MetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
-{
-       auto _file = dynamic_cast<MPEG::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __append_APIC(_file->ID3v2Tag(true), picture, size, mime_type);
-}
-
-int Mp3MetadataFile::getPicture(int index, void **picture, int *size, char **mime_type)
-{
-       auto _file = dynamic_cast<MPEG::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __get_APIC(_file->ID3v2Tag(), index, picture, size, mime_type);
-}
-
-int Mp3MetadataFile::removePicture(int index)
-{
-       auto _file = dynamic_cast<MPEG::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __remove_APIC(_file->ID3v2Tag(true), index);
-}
-
-int Mp3MetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
+static int __append_picture(File *f, metadata_editor_format_e format, const char *picture, size_t size, const char *mime_type)
 {
-       metadata_editor_retvm_if(file->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "File is readonly. Unable to modify");
+       metadata_editor_retvm_if(!f, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
 
-       auto _file = dynamic_cast<MPEG::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __set_ID3_tag(attribute, _file->ID3v1Tag(), _file->ID3v2Tag(true), value);
-}
-
-int Mp3MetadataFile::getMetadata(metadata_editor_attr_e attribute, char **value)
-{
-       auto _file = dynamic_cast<MPEG::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __get_ID3_tag(attribute, _file->ID3v1Tag(), _file->ID3v2Tag(), value);
-}
+       switch (format) {
+       case METADATA_EDITOR_FORMAT_MP3: {
+               auto _file = dynamic_cast<MPEG::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __append_APIC(_file->ID3v2Tag(true), picture, size, mime_type);
+       }
+       case METADATA_EDITOR_FORMAT_MP4: {
+               auto _file = dynamic_cast<MP4::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               auto tag = dynamic_cast<MP4::Tag*>(_file->tag());
+               MP4::CoverArtList lst;
+               auto format = MP4::CoverArt::Unknown;
+               if (strncmp(mime_type, MIME_TYPE_JPEG, strlen(MIME_TYPE_JPEG)) == 0)
+                       format = MP4::CoverArt::JPEG;
+               else if (strncmp(mime_type, MIME_TYPE_PNG, strlen(MIME_TYPE_PNG)) == 0)
+                       format = MP4::CoverArt::PNG;
 
-int Mp3MetadataFile::updateMetadata()
-{
-       auto _file = dynamic_cast<MPEG::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+               if (tag->contains("covr")) {
+                       metadata_editor_info("The item <covr> exists. Adding picture");
+                       lst = tag->item("covr").toCoverArtList();
+               }
 
-       auto tag1 = _file->ID3v1Tag();
+               lst.append(MP4::CoverArt(format, ByteVector(picture, size)));
+               tag->setItem("covr", lst);
 
-       if (!tag1 || tag1->isEmpty()) { // If no ID3v1 tag - prevent its creation
-               if (_file->save(MPEG::File::ID3v2 | MPEG::File::APE))
-                       return METADATA_EDITOR_ERROR_NONE;
-       } else {        // otherwise - save all tags in file
-               if (_file->save(MPEG::File::AllTags))
-                       return METADATA_EDITOR_ERROR_NONE;
+               return METADATA_EDITOR_ERROR_NONE;
        }
+       case METADATA_EDITOR_FORMAT_FLAC: {
+               auto _file = dynamic_cast<FLAC::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               auto frontCover = new FLAC::Picture;
 
-       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
-}
+               frontCover->setData(ByteVector(picture, size));
+               frontCover->setType(FLAC::Picture::FrontCover);
+               frontCover->setMimeType(mime_type);
 
-int Mp4MetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
-{
-       auto tag = dynamic_cast<MP4::Tag*>(file->tag());
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
-
-       MP4::CoverArtList lst;
-       auto format = MP4::CoverArt::Unknown;
-       if (strncmp(mime_type, MIME_TYPE_JPEG, strlen(MIME_TYPE_JPEG)) == 0)
-               format = MP4::CoverArt::JPEG;
-       else if (strncmp(mime_type, MIME_TYPE_PNG, strlen(MIME_TYPE_PNG)) == 0)
-               format = MP4::CoverArt::PNG;
-
-       if (tag->contains("covr")) {
-               metadata_editor_info("The item <covr> exists. Adding picture");
-               lst = tag->item("covr").toCoverArtList();
+               _file->addPicture(frontCover);
+               return METADATA_EDITOR_ERROR_NONE;
        }
-
-       lst.append(MP4::CoverArt(format, ByteVector(picture, size)));
-       tag->setItem("covr", lst);
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-int Mp4MetadataFile::getPicture(int index, void **picture, int *size, char **mime_type)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       auto tag = dynamic_cast<MP4::Tag*>(file->tag());
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
-
-       if (!(tag->contains("covr"))) {
-               metadata_editor_error("No item <covr> in file. No pictures in file");
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
+               auto _file = dynamic_cast<Ogg::Vorbis::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __append_ogg_picture(_file->tag(), picture, size, mime_type);
        }
-
-       auto lst = tag->item("covr").toCoverArtList();
-
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
-
-       auto pictureFrame = static_cast<MP4::CoverArt>(lst[index]);
-
-       int pictureSize = pictureFrame.data().size();
-       metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
-
-       *picture = g_memdup2(pictureFrame.data().data(), pictureSize);
-       *size = pictureSize;
-       *mime_type = __get_mime_type_from_cover_art(pictureFrame);
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-int Mp4MetadataFile::removePicture(int index)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       auto tag = dynamic_cast<MP4::Tag*>(file->tag());
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
-
-       if (!(tag->contains("covr"))) {
-               metadata_editor_error("No item <covr> in file. No pictures in file");
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       case METADATA_EDITOR_FORMAT_OGG_FLAC: {
+               auto _file = dynamic_cast<Ogg::FLAC::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __append_ogg_picture(_file->tag(), picture, size, mime_type);
        }
-
-       auto lst = tag->item("covr").toCoverArtList();
-
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
-
-       auto picIt = lst.begin();
-       std::advance(picIt, index);
-       lst.erase(picIt);
-
-       tag->setItem("covr", lst);      //?? FIX ME!
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-int Mp4MetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
-{
-       switch (attribute) {
-       case METADATA_EDITOR_ATTR_ARTIST:                       return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""ART", value);
-       case METADATA_EDITOR_ATTR_TITLE:                        return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""nam", value);
-       case METADATA_EDITOR_ATTR_ALBUM:                        return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""alb", value);
-       case METADATA_EDITOR_ATTR_GENRE:                        return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""gen", value);
-       case METADATA_EDITOR_ATTR_AUTHOR:                       return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""wrt", value);
-       case METADATA_EDITOR_ATTR_COPYRIGHT:            return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "cprt", value);
-       case METADATA_EDITOR_ATTR_DATE:                 return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""day", value);
-       case METADATA_EDITOR_ATTR_DESCRIPTION:          return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "desc", value);
-       case METADATA_EDITOR_ATTR_COMMENT:              return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""cmt", value);
-       case METADATA_EDITOR_ATTR_TRACK_NUM:            return __MP4_updateIntegerItem(dynamic_cast<MP4::Tag*>(file->tag()), "trkn", value);
-       case METADATA_EDITOR_ATTR_CONDUCTOR:            return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "cond", value);
-       case METADATA_EDITOR_ATTR_UNSYNCLYRICS: return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""lyr", value);
-       default:
-               metadata_editor_error("Invalid attribute [%d]", attribute);
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       case METADATA_EDITOR_FORMAT_WAV: {
+               auto _file = dynamic_cast<RIFF::WAV::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __append_APIC(dynamic_cast<ID3v2::Tag*>(_file->tag()), picture, size, mime_type);
        }
-}
-
-int Mp4MetadataFile::getMetadata(metadata_editor_attr_e attribute, char **value)
-{
-       switch (attribute) {                                    // Check which one of frame types was given to the function for processing
-       case METADATA_EDITOR_ATTR_ARTIST:                       return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""ART", value);
-       case METADATA_EDITOR_ATTR_TITLE:                        return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""nam", value);
-       case METADATA_EDITOR_ATTR_ALBUM:                        return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""alb", value);
-       case METADATA_EDITOR_ATTR_GENRE:                        return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""gen", value);
-       case METADATA_EDITOR_ATTR_AUTHOR:                       return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""wrt", value);
-       case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "cprt", value);
-       case METADATA_EDITOR_ATTR_DATE:                 return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""day", value);
-       case METADATA_EDITOR_ATTR_DESCRIPTION:          return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "desc", value);
-       case METADATA_EDITOR_ATTR_COMMENT:                      return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""cmt", value);
-       case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __MP4_getIntegerItem(dynamic_cast<MP4::Tag*>(file->tag()), "trkn", value);
-       case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "cond", value);
-       case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(file->tag()), "\xA9""lyr", value);
-       case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __MP4_getNumberOfPictures(dynamic_cast<MP4::Tag*>(file->tag()), value);
        default:
-               metadata_editor_error("Invalid attribute [%d]", attribute);
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-}
-
-int Mp4MetadataFile::updateMetadata()
-{
-       if (file->save())
                return METADATA_EDITOR_ERROR_NONE;
-
-       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
-}
-
-int FlacMetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
-{
-       auto _file = dynamic_cast<FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       auto frontCover = new FLAC::Picture;
-
-       frontCover->setData(ByteVector(picture, size));
-       frontCover->setType(FLAC::Picture::FrontCover);
-       frontCover->setMimeType(mime_type);
-
-       _file->addPicture(frontCover);
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-int FlacMetadataFile::getPicture(int index, void **picture, int *size, char **mime_type)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       auto _file = dynamic_cast<FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       auto lst = _file->pictureList();
-
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
-
-       auto pictureFrame = static_cast<FLAC::Picture*>(lst[index]);
-
-       int pictureSize = pictureFrame->data().size();
-       metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
-
-       *picture = g_memdup2(pictureFrame->data().data(), pictureSize);
-       *size = pictureSize;
-       *mime_type = __get_mime_type(pictureFrame->mimeType());
-
-       return METADATA_EDITOR_ERROR_NONE;
+       }
 }
 
-int FlacMetadataFile::removePicture(int index)
+static int __remove_picture(File *f, metadata_editor_format_e format, int index)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
+       metadata_editor_retvm_if(!f, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
 
-       auto _file = dynamic_cast<FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       switch (format) {
+       case METADATA_EDITOR_FORMAT_MP3: {
+               auto _file = dynamic_cast<MPEG::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __remove_APIC(_file->ID3v2Tag(true), index);
+       }
+       case METADATA_EDITOR_FORMAT_MP4: {
+               auto _file = dynamic_cast<MP4::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               auto tag = dynamic_cast<MP4::Tag*>(_file->tag());
 
-       auto lst = _file->pictureList();
+               metadata_editor_retvm_if(!(tag->contains("covr")), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "No picture");
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+               auto lst = tag->item("covr").toCoverArtList();
 
-       _file->removePicture(lst[index], true);
+               metadata_editor_retvm_if(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
 
-       return METADATA_EDITOR_ERROR_NONE;
-}
+               auto picIt = lst.begin();
+               std::advance(picIt, index);
+               lst.erase(picIt);
 
-int FlacMetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
-{
-       auto _file = dynamic_cast<FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       auto xtag = _file->xiphComment(true);
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to create Xiph Comment. Can not proceed metadata updating");
+               tag->setItem("covr", lst);      //?? FIX ME!
 
-       switch (attribute) {
-               case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_updateFieldValue(xtag, "ARTIST", value);
-               case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_updateFieldValue(xtag, "TITLE", value);
-               case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_updateFieldValue(xtag, "ALBUM", value);
-               case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_updateFieldValue(xtag, "GENRE", value);
-               case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_updateFieldValue(xtag, "COMPOSER", value);
-               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_updateFieldValue(xtag, "COPYRIGHT", value);
-               case METADATA_EDITOR_ATTR_DATE:                 return __xiph_updateFieldValue(xtag, "DATE", value);
-               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_updateFieldValue(xtag, "DESCRIPTION", value);
-               case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_updateFieldValue(xtag, "COMMENT", value);
-               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_updateFieldValue(xtag, "TRACKNUMBER", value);
-               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_updateFieldValue(xtag, "CONDUCTOR", value);
-               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_updateFieldValue(xtag, "LYRICS", value);
-               default:
-                       metadata_editor_error("Invalid attribute [%d]", attribute);
-                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+               return METADATA_EDITOR_ERROR_NONE;
        }
-}
-
-int FlacMetadataFile::getMetadata(metadata_editor_attr_e attribute, char **value)
-{
-       auto _file = dynamic_cast<FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       case METADATA_EDITOR_FORMAT_FLAC: {
+               auto _file = dynamic_cast<FLAC::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               auto lst = _file->pictureList();
 
-       auto xtag = _file->xiphComment(false);
+               metadata_editor_retvm_if(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
 
-       switch (attribute) {
-               case METADATA_EDITOR_ATTR_ARTIST:                       return __xiph_getFieldValue(xtag, "ARTIST", value);
-               case METADATA_EDITOR_ATTR_TITLE:                        return __xiph_getFieldValue(xtag, "TITLE", value);
-               case METADATA_EDITOR_ATTR_ALBUM:                        return __xiph_getFieldValue(xtag, "ALBUM", value);
-               case METADATA_EDITOR_ATTR_GENRE:                        return __xiph_getFieldValue(xtag, "GENRE", value);
-               case METADATA_EDITOR_ATTR_AUTHOR:                       return __xiph_getFieldValue(xtag, "COMPOSER", value);
-               case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __xiph_getFieldValue(xtag, "COPYRIGHT", value);
-               case METADATA_EDITOR_ATTR_DATE:                 return __xiph_getFieldValue(xtag, "DATE", value);
-               case METADATA_EDITOR_ATTR_DESCRIPTION:          return __xiph_getFieldValue(xtag, "DESCRIPTION", value);
-               case METADATA_EDITOR_ATTR_COMMENT:                      return __xiph_getFieldValue(xtag, "COMMENT", value);
-               case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __xiph_getFieldValue(xtag, "TRACKNUMBER", value);
-               case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __xiph_getFieldValue(xtag, "CONDUCTOR", value);
-               case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __xiph_getFieldValue(xtag, "LYRICS", value);
-               case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __FLAC_getNumberOfPictures(_file, value);
-               default:
-                       metadata_editor_error("Invalid attribute [%d]", attribute);
-                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+               _file->removePicture(lst[index], true);
+               return METADATA_EDITOR_ERROR_NONE;
        }
-}
-
-int FlacMetadataFile::updateMetadata()
-{
-       if (file->save())
+       case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
+               auto _file = dynamic_cast<Ogg::Vorbis::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __remove_ogg_picture(_file->tag(), index);
+       }
+       case METADATA_EDITOR_FORMAT_OGG_FLAC: {
+               auto _file = dynamic_cast<Ogg::FLAC::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __remove_ogg_picture(_file->tag(), index);
+       }
+       case METADATA_EDITOR_FORMAT_WAV: {
+               auto _file = dynamic_cast<RIFF::WAV::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __remove_APIC(dynamic_cast<ID3v2::Tag*>(_file->tag()), index);
+       }
+       default:
                return METADATA_EDITOR_ERROR_NONE;
-
-       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
-}
-
-int OggVorbisMetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
-{
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __append_ogg_picture(_file->tag(), picture, size, mime_type);
+       }
 }
 
-int OggVorbisMetadataFile::getPicture(int index, void **picture, int *size, char **mime_type)
+static int __get_picture(File *f, metadata_editor_format_e format, int index, void **picture, int *size, char **mime_type)
 {
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __get_ogg_picture(_file->tag(), index, picture, size, mime_type);
-}
+       metadata_editor_retvm_if(!f, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+       metadata_editor_retvm_if(!picture, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture");
+       metadata_editor_retvm_if(!size, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid size");
+       metadata_editor_retvm_if(!mime_type, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid mime_type");
 
-int OggVorbisMetadataFile::removePicture(int index)
-{
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       switch (format) {
+       case METADATA_EDITOR_FORMAT_MP3: {
+               auto _file = dynamic_cast<MPEG::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __get_APIC(_file->ID3v2Tag(), index, picture, size, mime_type);
+       }
+       case METADATA_EDITOR_FORMAT_MP4: {
+               auto _file = dynamic_cast<MP4::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               auto tag = dynamic_cast<MP4::Tag *>(_file->tag());
 
-       return __remove_ogg_picture(_file->tag(), index);
-}
+               metadata_editor_retvm_if(!(tag->contains("covr")), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "No picture");
 
-int OggVorbisMetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
-{
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+               auto lst = tag->item("covr").toCoverArtList();
 
-       auto xtag = _file->tag();
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
+               metadata_editor_retvm_if(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
 
-       return __set_ogg_metadata(xtag, attribute, value);
-}
+               auto pictureFrame = static_cast<MP4::CoverArt>(lst[index]);
 
-int OggVorbisMetadataFile::getMetadata(metadata_editor_attr_e attribute, char **value)
-{
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+               int pictureSize = pictureFrame.data().size();
+               metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
 
-       return __get_ogg_metadata(_file->tag(), attribute, value);
-}
+               *picture = g_memdup2(pictureFrame.data().data(), pictureSize);
+               *size = pictureSize;
+               *mime_type = __get_mime_type_from_cover_art(pictureFrame);
 
-int OggVorbisMetadataFile::updateMetadata()
-{
-       if (file->save())
                return METADATA_EDITOR_ERROR_NONE;
+       }
+       case METADATA_EDITOR_FORMAT_FLAC: {
+               auto _file = dynamic_cast<FLAC::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               auto lst = _file->pictureList();
 
-       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
-}
-
-int OggFlacMetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
-{
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __append_ogg_picture(_file->tag(), picture, size, mime_type);
-}
+               metadata_editor_retvm_if(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
 
-int OggFlacMetadataFile::getPicture(int index, void **picture, int *size, char **mime_type)
-{
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+               auto pictureFrame = static_cast<FLAC::Picture*>(lst[index]);
 
-       return __get_ogg_picture(_file->tag(), index, picture, size, mime_type);
-}
+               int pictureSize = pictureFrame->data().size();
+               metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
 
-int OggFlacMetadataFile::removePicture(int index)
-{
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+               *picture = g_memdup2(pictureFrame->data().data(), pictureSize);
+               *size = pictureSize;
+               *mime_type = __get_mime_type(pictureFrame->mimeType());
 
-       return __remove_ogg_picture(_file->tag(), index);
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
+               auto _file = dynamic_cast<Ogg::Vorbis::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __get_ogg_picture(_file->tag(), index, picture, size, mime_type);
+       }
+       case METADATA_EDITOR_FORMAT_OGG_FLAC: {
+               auto _file = dynamic_cast<Ogg::FLAC::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __get_ogg_picture(_file->tag(), index, picture, size, mime_type);
+       }
+       case METADATA_EDITOR_FORMAT_WAV:{
+               auto _file = dynamic_cast<RIFF::WAV::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               return __get_APIC(_file->tag(), index, picture, size, mime_type);
+       }
+       default:
+               return METADATA_EDITOR_ERROR_NONE;
+       }
 }
 
-int OggFlacMetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
+static int __get_picture_number(File *f, metadata_editor_format_e format, char **value)
 {
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       auto xtag = _file->tag();
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
-
-       return __set_ogg_metadata(xtag, attribute, value);
-}
+       metadata_editor_retvm_if(!f, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+       metadata_editor_retvm_if(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
 
-int OggFlacMetadataFile::getMetadata(metadata_editor_attr_e attribute, char **value)
-{
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       switch (format) {
+       case METADATA_EDITOR_FORMAT_MP3: {
+               auto _file = dynamic_cast<MPEG::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               *value = g_strdup_printf("%u", _file->ID3v2Tag() ? _file->ID3v2Tag()->frameListMap()["APIC"].size() : 0);
+               break;
+       }
+       case METADATA_EDITOR_FORMAT_MP4: {
+               auto _file = dynamic_cast<MP4::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               if (_file->tag() && _file->tag()->contains("covr"))
+                       *value = g_strdup_printf("%u", _file->tag()->item("covr").toCoverArtList().size());
+               else
+                       *value = g_strdup_printf("0");
+               break;
+       }
+       case METADATA_EDITOR_FORMAT_FLAC: {
+               auto _file = dynamic_cast<FLAC::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               *value = g_strdup_printf("%u", _file ? _file->pictureList().size() : 0);
+               break;
+       }
+       case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
+               auto _file = dynamic_cast<Ogg::Vorbis::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               *value = g_strdup_printf("%u", _file->tag() ? _file->tag()->pictureList().size() : 0);
+               break;
+       }
+       case METADATA_EDITOR_FORMAT_OGG_FLAC: {
+               auto _file = dynamic_cast<Ogg::FLAC::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               *value = g_strdup_printf("%u", _file->tag() ? _file->tag()->pictureList().size() : 0);
+               break;
+       }
+       case METADATA_EDITOR_FORMAT_WAV: {
+               auto _file = dynamic_cast<RIFF::WAV::File *>(f);
+               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+               auto tag = dynamic_cast<ID3v2::Tag *>(_file->tag());
+               metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid tag");
+               *value = g_strdup_printf("%u", tag ? tag->frameListMap()["APIC"].size() : 0);
+               break;
+       }
+       default:
+               break;
+       }
 
-       return __get_ogg_metadata(_file->tag(), attribute, value);
+       return METADATA_EDITOR_ERROR_NONE;
 }
 
-int OggFlacMetadataFile::updateMetadata()
+static int __set_to_property_map(File *file, String key, const char *value)
 {
-       if (file->save())
-               return METADATA_EDITOR_ERROR_NONE;
+       metadata_editor_retvm_if(!file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+       metadata_editor_retvm_if(key.isEmpty(), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid key");
 
-       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
-}
+       PropertyMap tags = file->properties();
 
-int WavMetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
-{
-       return __append_APIC(dynamic_cast<ID3v2::Tag*>(file->tag()), picture, size, mime_type);
-}
+       if (value == NULL || strlen(value) == 0)
+               tags.erase(key);
+       else
+               tags.replace(key, StringList(String(value, String::UTF8)));
 
-int WavMetadataFile::getPicture(int index, void **picture, int *size, char **mime_type)
-{
-       auto _file = dynamic_cast<RIFF::WAV::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       file->setProperties(tags);
 
-       return __get_APIC(_file->tag(), index, picture, size, mime_type);
+       return METADATA_EDITOR_ERROR_NONE;
 }
 
-int WavMetadataFile::removePicture(int index)
+static int __get_from_property_map(PropertyMap tags, String key, char **value)
 {
-       return __remove_APIC(dynamic_cast<ID3v2::Tag*>(file->tag()), index);
-}
+       metadata_editor_retvm_if(key.isEmpty(), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid field_name");
+       metadata_editor_retvm_if(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
 
-int WavMetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
-{
-       auto _file = dynamic_cast<RIFF::WAV::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       if (tags.isEmpty())
+               return METADATA_EDITOR_ERROR_NONE;
 
-       return __set_ID3_tag(attribute, NULL, _file->tag(), value);
-}
+       PropertyMap::ConstIterator found = tags.find(key);
 
-int WavMetadataFile::getMetadata(metadata_editor_attr_e attribute, char **value)
-{
-       auto _file = dynamic_cast<RIFF::WAV::File*>(file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       if (found != tags.end())
+               *value = g_strdup(found->second[0].toCString(true));
 
-       return __get_ID3_tag(attribute, NULL, _file->tag(), value);
+       return METADATA_EDITOR_ERROR_NONE;
 }
 
-int WavMetadataFile::updateMetadata()
-{
-       if (file->save())
-               return METADATA_EDITOR_ERROR_NONE;
-
-       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
-}
+class OggFileTypeResolver : public TagLib::FileRef::FileTypeResolver {
+       TagLib::File *createFile(TagLib::FileName fileName, bool, AudioProperties::ReadStyle) const {
+               char ext[EXT_LEN] = {0, };
+               if (__metadata_editor_get_file_ext(fileName, ext, EXT_LEN)) {
+                       if (strcasecmp(ext, "OGG") == 0) {
+                               File *file = new Ogg::FLAC::File(fileName);
+                               if(file->isValid())
+                                       return file;
+                               delete file;
+                               return new Ogg::Vorbis::File(fileName);
+                       }
+               }
+               return 0;
+       }
+};
 
 extern "C" int metadata_editor_create(metadata_editor_h *metadata)
 {
-       metadata_editor_debug_fenter();
-
        metadata_editor_retvm_if(!metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
 
        metadata_editor_s* _metadata = (metadata_editor_s*)malloc(sizeof(metadata_editor_s));
@@ -1432,7 +656,7 @@ extern "C" int metadata_editor_destroy(metadata_editor_h metadata)
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
        metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
 
-       delete _metadata->intf;
+       delete _metadata->fref;
        free(_metadata);
 
        return METADATA_EDITOR_ERROR_NONE;
@@ -1441,62 +665,36 @@ extern "C" int metadata_editor_destroy(metadata_editor_h metadata)
 extern "C" int metadata_editor_set_path(metadata_editor_h metadata, const char *path)
 {
        int ret = METADATA_EDITOR_ERROR_NONE;
-       int media_type = METADATA_EDITOR_FORMAT_NOTYPE;
+       metadata_editor_format_e media_type = METADATA_EDITOR_FORMAT_NOTYPE;
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
 
-       metadata_editor_debug_fenter();
-
        metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
 
        ret = __check_file_validity(path);
        metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid path");
 
        media_type = __metadata_editor_get_file_type(path);
+       metadata_editor_retvm_if(media_type == METADATA_EDITOR_FORMAT_NOTYPE, ret, "Not supported type [%d]", media_type);
 
-       if (_metadata->intf) {
-               metadata_editor_info("file free [%p]", _metadata->intf);
-               delete _metadata->intf;
+       if (_metadata->fref) {
+               metadata_editor_info("file free [%p]", _metadata->fref);
+               delete _metadata->fref;
        }
 
        metadata_editor_debug("media_type : [%d]", media_type);
-
+       _metadata->format = media_type;
        try {
-               switch (media_type) {
-                       case METADATA_EDITOR_FORMAT_MP3:
-                               _metadata->intf = new Mp3MetadataFile(path);
-                               break;
-
-                       case METADATA_EDITOR_FORMAT_MP4:
-                               _metadata->intf = new Mp4MetadataFile(path);
-                               break;
-
-                       case METADATA_EDITOR_FORMAT_FLAC:
-                               _metadata->intf = new FlacMetadataFile(path);
-                               break;
-
-                       case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-                               _metadata->intf = new OggVorbisMetadataFile(path);
-                               break;
-
-                       case METADATA_EDITOR_FORMAT_OGG_FLAC:
-                               _metadata->intf = new OggFlacMetadataFile(path);
-                               break;
-
-                       case METADATA_EDITOR_FORMAT_WAV:
-                               _metadata->intf = new WavMetadataFile(path);
-                               break;
-
-                       default:
-                               metadata_editor_error("Not supported file type [%d]", media_type);
-                               return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
-               }
+               //FileTypeResolver is not deleted until terminated. So, it should be called only once.
+               static auto oggResolver = FileRef::addFileTypeResolver(new OggFileTypeResolver);
+               metadata_editor_info("%p", oggResolver);
+               _metadata->fref = new FileRef(path);
        } catch (const std::bad_alloc &ex) {
-               metadata_editor_retvm_if(!_metadata->intf, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
+               metadata_editor_retvm_if(!_metadata->fref, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
        }
 
-       if (!_metadata->intf->isOpen()) {
-               delete _metadata->intf;
-               _metadata->intf = nullptr;
+       if (!_metadata->fref->file()->isOpen()) {
+               delete _metadata->fref;
+               _metadata->fref = nullptr;
                return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
        }
 
@@ -1505,13 +703,15 @@ extern "C" int metadata_editor_set_path(metadata_editor_h metadata, const char *
 
 extern "C" int metadata_editor_append_picture(metadata_editor_h metadata, const char *path)
 {
+       int ret = METADATA_EDITOR_ERROR_NONE;
        char *picture = NULL;
        size_t size = 0;
        char *mime_type = NULL;
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
 
-       int ret = __check_metadata_set_parameter(_metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
+       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
+       metadata_editor_retvm_if(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       metadata_editor_retvm_if(_metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
        metadata_editor_retvm_if(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
 
        ret = __check_file_validity(path);
@@ -1520,7 +720,7 @@ extern "C" int metadata_editor_append_picture(metadata_editor_h metadata, const
        ret = __metadata_editor_get_picture_info(path, &picture, &size, &mime_type);
        metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "File does not exist or you have no rights to open it");
 
-       ret = _metadata->intf->appendPicture(picture, size, mime_type);
+       ret = __append_picture(_metadata->fref->file(), _metadata->format, picture, size, mime_type);
 
        g_free(picture);
        g_free(mime_type);
@@ -1532,51 +732,118 @@ extern "C" int metadata_editor_remove_picture(metadata_editor_h metadata, int in
 {
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
 
-       int ret = __check_metadata_set_parameter(_metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
+       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
+       metadata_editor_retvm_if(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       metadata_editor_retvm_if(_metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
 
-       return _metadata->intf->removePicture(index);
+       return __remove_picture(_metadata->fref->file(), _metadata->format, index);
 }
 
 extern "C" int metadata_editor_get_picture(metadata_editor_h metadata, int index, void **picture, int *size, char **mime_type)
 {
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
 
-       int ret = __check_metadata_get_parameter(_metadata, mime_type);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
+       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
+       metadata_editor_retvm_if(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
        metadata_editor_retvm_if(!picture, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture");
        metadata_editor_retvm_if(!size, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid size");
+       metadata_editor_retvm_if(!mime_type, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid mime_type");
 
-       return _metadata->intf->getPicture(index, picture, size, mime_type);
+       return __get_picture(_metadata->fref->file(), _metadata->format, index, picture, size, mime_type);
 }
 
 extern "C" int metadata_editor_set_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, const char *value)
 {
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
 
-       int ret = __check_metadata_set_parameter(_metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
+       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
+       metadata_editor_retvm_if(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       metadata_editor_retvm_if(_metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
 
-       return _metadata->intf->setMetadata(attribute, value);
+       switch (attribute) {
+       case METADATA_EDITOR_ATTR_ARTIST:
+               return __set_to_property_map(_metadata->fref->file(), String("ARTIST"), value);
+       case METADATA_EDITOR_ATTR_TITLE:
+               return __set_to_property_map(_metadata->fref->file(), String("TITLE"), value);
+       case METADATA_EDITOR_ATTR_ALBUM:
+               return __set_to_property_map(_metadata->fref->file(), String("ALBUM"), value);
+       case METADATA_EDITOR_ATTR_GENRE:
+               return __set_to_property_map(_metadata->fref->file(), String("GENRE"), value);
+       case METADATA_EDITOR_ATTR_AUTHOR:
+               return __set_to_property_map(_metadata->fref->file(), String("COMPOSER"), value);
+       case METADATA_EDITOR_ATTR_COPYRIGHT:
+               return __set_to_property_map(_metadata->fref->file(), String("COPYRIGHT"), value);
+       case METADATA_EDITOR_ATTR_DATE:
+               return __set_to_property_map(_metadata->fref->file(), String("DATE"), value);
+       case METADATA_EDITOR_ATTR_DESCRIPTION:
+               return __set_to_property_map(_metadata->fref->file(), String("DESCRIPTION"), value);
+       case METADATA_EDITOR_ATTR_COMMENT:
+               return __set_to_property_map(_metadata->fref->file(), String("COMMENT"), value);
+       case METADATA_EDITOR_ATTR_TRACK_NUM:
+               return __set_to_property_map(_metadata->fref->file(), String("TRACKNUMBER"), value);
+       case METADATA_EDITOR_ATTR_CONDUCTOR:
+               return __set_to_property_map(_metadata->fref->file(), String("CONDUCTOR"), value);
+       case METADATA_EDITOR_ATTR_UNSYNCLYRICS:
+               return __set_to_property_map(_metadata->fref->file(), String("LYRICS"), value);
+       default:
+               metadata_editor_error("Invalid attribute");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
 }
 
 extern "C" int metadata_editor_get_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, char **value)
 {
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
 
-       int ret = __check_metadata_get_parameter(_metadata, value);
+       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
+       metadata_editor_retvm_if(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       metadata_editor_retvm_if(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
 
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
+       PropertyMap tags = _metadata->fref->file()->properties();
 
-       return _metadata->intf->getMetadata(attribute, value);
+       switch (attribute) {
+       case METADATA_EDITOR_ATTR_ARTIST:
+               return __get_from_property_map(tags, String("ARTIST"), value);
+       case METADATA_EDITOR_ATTR_TITLE:
+               return __get_from_property_map(tags, String("TITLE"), value);
+       case METADATA_EDITOR_ATTR_ALBUM:
+               return __get_from_property_map(tags, String("ALBUM"), value);
+       case METADATA_EDITOR_ATTR_GENRE:
+               return __get_from_property_map(tags, String("GENRE"), value);
+       case METADATA_EDITOR_ATTR_AUTHOR:
+               return __get_from_property_map(tags, String("COMPOSER"), value);
+       case METADATA_EDITOR_ATTR_COPYRIGHT:
+               return __get_from_property_map(tags, String("COPYRIGHT"), value);
+       case METADATA_EDITOR_ATTR_DATE:
+               return __get_from_property_map(tags, String("DATE"), value);
+       case METADATA_EDITOR_ATTR_DESCRIPTION:
+               return __get_from_property_map(tags, String("DESCRIPTION"), value);
+       case METADATA_EDITOR_ATTR_COMMENT:
+               return __get_from_property_map(tags, String("COMMENT"), value);
+       case METADATA_EDITOR_ATTR_TRACK_NUM:
+               return __get_from_property_map(tags, String("TRACKNUMBER"), value);
+       case METADATA_EDITOR_ATTR_CONDUCTOR:
+               return __get_from_property_map(tags, String("CONDUCTOR"), value);
+       case METADATA_EDITOR_ATTR_UNSYNCLYRICS:
+               return __get_from_property_map(tags, String("LYRICS"), value);
+       case METADATA_EDITOR_ATTR_PICTURE_NUM:
+               return __get_picture_number(_metadata->fref->file(), _metadata->format, value);
+       default:
+               metadata_editor_error("Invalid attribute [%d]", attribute);
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
 }
 
 extern "C" int metadata_editor_update_metadata(metadata_editor_h metadata)
 {
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
 
-       int ret = __check_metadata_set_parameter(_metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
+       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
+       metadata_editor_retvm_if(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       metadata_editor_retvm_if(_metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
 
-       return _metadata->intf->updateMetadata();
-}
+       if (!_metadata->fref->file()->save())
+               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+
+       return METADATA_EDITOR_ERROR_NONE;
+}
\ No newline at end of file