Refactoring using abstract class for metadata file interface 04/261804/7 accepted/tizen/6.5/unified/20211028.101504 accepted/tizen/unified/20210804.043636 submit/tizen/20210803.230150 submit/tizen_6.5/20211028.161801 tizen_6.5.m2_release
authorSeungbae Shin <seungbae.shin@samsung.com>
Mon, 26 Jul 2021 16:37:33 +0000 (01:37 +0900)
committerSeungbae Shin <seungbae.shin@samsung.com>
Thu, 29 Jul 2021 03:29:25 +0000 (03:29 +0000)
Change-Id: Iab450bd815bb3509d447b2f7bac35610cc66294f

src/metadata_editor.cpp

index 17a6478971ccae8c1681cca6c25129dd163b343d..668a78642be7ad3e37dd869e2116cba77cdd12b1 100755 (executable)
@@ -47,9 +47,136 @@ 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 {
-       File*   file;
-       int     filetype;
+       MetadataFile* intf;
 } metadata_editor_s;
 
 typedef enum {
@@ -65,7 +192,7 @@ typedef enum {
 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->file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       metadata_editor_retvm_if(!metadata->intf, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
 
        return METADATA_EDITOR_ERROR_NONE;
 }
@@ -77,7 +204,7 @@ static int __check_metadata_set_parameter(metadata_editor_s *metadata)
        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->file->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "File is readonly. Unable to modify");
+       metadata_editor_retvm_if(metadata->intf->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "File is readonly. Unable to modify");
 
        return METADATA_EDITOR_ERROR_NONE;
 }
@@ -580,20 +707,7 @@ static int __metadata_editor_get_picture_info(const char *path, char **picture,
        return ret;
 }
 
-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 = g_new0(metadata_editor_s, 1);
-
-       _metadata->filetype = METADATA_EDITOR_FORMAT_NOTYPE;
-
-       *metadata = (metadata_editor_h)_metadata;
 
-       return METADATA_EDITOR_ERROR_NONE;
-}
 
 static int __check_file_validity(const char *path)
 {
@@ -614,77 +728,6 @@ static int __check_file_validity(const char *path)
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-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_s *_metadata = (metadata_editor_s*)metadata;
-       File *_file = NULL;
-
-       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);
-
-       if (_metadata->file) {
-               metadata_editor_info("file free [%p]", _metadata->file);
-               delete _metadata->file;
-
-               _metadata->file = NULL;
-               _metadata->filetype = METADATA_EDITOR_FORMAT_NOTYPE;
-       }
-
-       metadata_editor_debug("media_type : [%d]", media_type);
-
-       try {
-       switch (media_type) {
-       case METADATA_EDITOR_FORMAT_MP3:
-               _file = new MPEG::File(path);
-               break;
-
-       case METADATA_EDITOR_FORMAT_MP4:
-               _file = new MP4::File(path);
-               break;
-
-       case METADATA_EDITOR_FORMAT_FLAC:
-               _file = new FLAC::File(path);
-               break;
-
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-               _file = new Ogg::Vorbis::File(path);
-               break;
-
-       case METADATA_EDITOR_FORMAT_OGG_FLAC:
-               _file = new Ogg::FLAC::File(path);
-               break;
-
-       case METADATA_EDITOR_FORMAT_WAV:
-               _file = new RIFF::WAV::File(path);
-               break;
-
-       default:
-               metadata_editor_error("Not supported file type [%d]", media_type);
-               return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
-       }
-       } catch (const std::bad_alloc &ex) {
-               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
-       }
-
-       if (!_file->isOpen()) {
-               metadata_editor_error("The file was not found. Pointer address is %p", _file);
-               delete _file;
-               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
-       }
-
-       _metadata->file = _file;
-       _metadata->filetype = media_type;
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
 
 static int __get_ID3_tag(metadata_editor_attr_e attribute, ID3v1::Tag *tag1, ID3v2::Tag *tag2, char **value)
 {
@@ -708,78 +751,6 @@ static int __get_ID3_tag(metadata_editor_attr_e attribute, ID3v1::Tag *tag1, ID3
        }
 }
 
-static int __metadata_editor_get_mp3_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_get_parameter(metadata, value);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<MPEG::File*>(metadata->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);
-}
-
-static int __metadata_editor_get_mp4_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_get_parameter(metadata, value);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
-
-       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*>(metadata->file->tag()), "\xA9""ART", value);
-       case METADATA_EDITOR_ATTR_TITLE:                        return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""nam", value);
-       case METADATA_EDITOR_ATTR_ALBUM:                        return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""alb", value);
-       case METADATA_EDITOR_ATTR_GENRE:                        return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""gen", value);
-       case METADATA_EDITOR_ATTR_AUTHOR:                       return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""wrt", value);
-       case METADATA_EDITOR_ATTR_COPYRIGHT:                    return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "cprt", value);
-       case METADATA_EDITOR_ATTR_DATE:                 return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""day", value);
-       case METADATA_EDITOR_ATTR_DESCRIPTION:          return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "desc", value);
-       case METADATA_EDITOR_ATTR_COMMENT:                      return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""cmt", value);
-       case METADATA_EDITOR_ATTR_TRACK_NUM:                    return __MP4_getIntegerItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "trkn", value);
-       case METADATA_EDITOR_ATTR_CONDUCTOR:                    return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "cond", value);
-       case METADATA_EDITOR_ATTR_UNSYNCLYRICS:                 return __MP4_getStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""lyr", value);
-       case METADATA_EDITOR_ATTR_PICTURE_NUM:                  return __MP4_getNumberOfPictures(dynamic_cast<MP4::Tag*>(metadata->file->tag()), value);
-       default:
-               metadata_editor_error("Invalid attribute [%d]", attribute);
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-}
-
-static int __metadata_editor_get_flac_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_get_parameter(metadata, value);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<FLAC::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       auto xtag = _file->xiphComment(false);
-
-       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;
-       }
-}
-
 static int __get_ogg_metadata(Ogg::XiphComment *xtag, metadata_editor_attr_e attribute, char **value)
 {
        switch (attribute) {
@@ -802,77 +773,6 @@ static int __get_ogg_metadata(Ogg::XiphComment *xtag, metadata_editor_attr_e att
        }
 }
 
-static int __metadata_editor_get_ogg_vorbis_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_get_parameter(metadata, value);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __get_ogg_metadata(_file->tag(), attribute, value);
-}
-
-static int __metadata_editor_get_ogg_flac_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_get_parameter(metadata, value);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __get_ogg_metadata(_file->tag(), attribute, value);
-}
-
-static int __metadata_editor_get_wav_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, char **value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_get_parameter(metadata, value);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<RIFF::WAV::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __get_ID3_tag(attribute, NULL, _file->tag(), value);
-}
-
-extern "C" int metadata_editor_get_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, char **value)
-{
-       metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
-       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-
-       metadata_editor_debug("file format [%d]", _metadata->filetype);
-
-       switch (_metadata->filetype) {
-       case METADATA_EDITOR_FORMAT_MP3:
-               return __metadata_editor_get_mp3_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_MP4:
-               return __metadata_editor_get_mp4_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_FLAC:
-               return __metadata_editor_get_flac_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-               return __metadata_editor_get_ogg_vorbis_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_OGG_FLAC:
-               return __metadata_editor_get_ogg_flac_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_WAV:
-               return __metadata_editor_get_wav_metadata(_metadata, attribute, value);
-
-       default:
-               metadata_editor_error("Invalid file type [%d]", _metadata->filetype);
-               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");
@@ -898,77 +798,6 @@ static int __set_ID3_tag(metadata_editor_attr_e attribute, ID3v1::Tag *tag1, ID3
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __metadata_editor_set_mp3_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, const char *value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_set_parameter(metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<MPEG::File*>(metadata->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);
-}
-
-static int __metadata_editor_set_mp4_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, const char *value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_set_parameter(metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
-
-       switch (attribute) {
-       case METADATA_EDITOR_ATTR_ARTIST:                       return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""ART", value);
-       case METADATA_EDITOR_ATTR_TITLE:                        return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""nam", value);
-       case METADATA_EDITOR_ATTR_ALBUM:                        return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""alb", value);
-       case METADATA_EDITOR_ATTR_GENRE:                        return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""gen", value);
-       case METADATA_EDITOR_ATTR_AUTHOR:                       return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""wrt", value);
-       case METADATA_EDITOR_ATTR_COPYRIGHT:            return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "cprt", value);
-       case METADATA_EDITOR_ATTR_DATE:                 return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""day", value);
-       case METADATA_EDITOR_ATTR_DESCRIPTION:          return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "desc", value);
-       case METADATA_EDITOR_ATTR_COMMENT:              return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""cmt", value);
-       case METADATA_EDITOR_ATTR_TRACK_NUM:            return __MP4_updateIntegerItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "trkn", value);
-       case METADATA_EDITOR_ATTR_CONDUCTOR:            return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "cond", value);
-       case METADATA_EDITOR_ATTR_UNSYNCLYRICS: return __MP4_updateStringItem(dynamic_cast<MP4::Tag*>(metadata->file->tag()), "\xA9""lyr", value);
-       default:
-               metadata_editor_error("Invalid attribute [%d]", attribute);
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-}
-
-static int __metadata_editor_set_flac_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, const char *value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_set_parameter(metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<FLAC::File*>(metadata->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");
-
-       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 int __set_ogg_metadata(Ogg::XiphComment *xtag, metadata_editor_attr_e attribute, const char *value)
 {
        switch (attribute) {
@@ -990,149 +819,27 @@ static int __set_ogg_metadata(Ogg::XiphComment *xtag, metadata_editor_attr_e att
        }
 }
 
-static int __metadata_editor_set_ogg_vorbis_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, const char *value)
+static char * __get_mime_type(const String& mime_type)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_set_parameter(metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
+       if (mime_type == MIME_TYPE_JPEG || mime_type == MIME_TYPE_PNG)
+               return g_strdup(mime_type.toCString());
 
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       return NULL;
+}
 
-       auto xtag = _file->tag();
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
+static char * __get_mime_type_from_cover_art(const MP4::CoverArt& cover_art)
+{
+       if (cover_art.format() == MP4::CoverArt::JPEG)
+               return g_strdup(MIME_TYPE_JPEG);
+       else if (cover_art.format() == MP4::CoverArt::PNG)
+               return g_strdup(MIME_TYPE_PNG);
 
-       return __set_ogg_metadata(xtag, attribute, value);
+       return NULL;
 }
 
-static int __metadata_editor_set_ogg_flac_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, const char *value)
+static int __is_valid_picture_index(bool is_empty, unsigned int list_size, int index)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_set_parameter(metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(metadata->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);
-}
-
-static int __metadata_editor_set_wav_metadata(metadata_editor_s *metadata, metadata_editor_attr_e attribute, const char *value)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-
-       ret = __check_metadata_set_parameter(metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
-
-       auto _file = dynamic_cast<RIFF::WAV::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-       return __set_ID3_tag(attribute, NULL, _file->tag(), value);
-}
-
-extern "C" int metadata_editor_set_metadata(metadata_editor_h metadata, metadata_editor_attr_e attribute, const char *value)
-{
-       metadata_editor_s *_metadata = (metadata_editor_s*) metadata;
-       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-
-       metadata_editor_debug("file format [%d]", _metadata->filetype);
-
-       switch (_metadata->filetype) {
-       case METADATA_EDITOR_FORMAT_MP3:
-               return __metadata_editor_set_mp3_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_MP4:
-               return __metadata_editor_set_mp4_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_FLAC:
-               return __metadata_editor_set_flac_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-               return __metadata_editor_set_ogg_vorbis_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_OGG_FLAC:
-               return __metadata_editor_set_ogg_flac_metadata(_metadata, attribute, value);
-
-       case METADATA_EDITOR_FORMAT_WAV:
-               return __metadata_editor_set_wav_metadata(_metadata, attribute, value);
-
-       default:
-               metadata_editor_error("Invalid file type [%d]", _metadata->filetype);
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
-}
-
-extern "C" int metadata_editor_update_metadata(metadata_editor_h metadata)
-{
-       int ret = METADATA_EDITOR_ERROR_NONE;
-       metadata_editor_s *_metadata = (metadata_editor_s*) metadata;
-
-       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_debug("file format [%d]", _metadata->filetype);
-
-       switch (_metadata->filetype) {
-       case METADATA_EDITOR_FORMAT_MP3: {
-               auto _file = dynamic_cast<MPEG::File*>(_metadata->file);
-               metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
-
-               auto tag1 = _file->ID3v1Tag();
-
-               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_OPERATION_FAILED;
-       }
-
-       case METADATA_EDITOR_FORMAT_MP4: {
-       case METADATA_EDITOR_FORMAT_FLAC:
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-       case METADATA_EDITOR_FORMAT_OGG_FLAC:
-       case METADATA_EDITOR_FORMAT_WAV:
-               if (_metadata->file->save())
-                       return METADATA_EDITOR_ERROR_NONE;
-
-               return METADATA_EDITOR_ERROR_OPERATION_FAILED;
-       }
-
-       default:
-               metadata_editor_error("Invalid file type [%d]", _metadata->filetype);
-               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)
-               return g_strdup(mime_type.toCString());
-
-       return NULL;
-}
-
-static char * __get_mime_type_from_cover_art(const MP4::CoverArt& cover_art)
-{
-       if (cover_art.format() == MP4::CoverArt::JPEG)
-               return g_strdup(MIME_TYPE_JPEG);
-       else if (cover_art.format() == MP4::CoverArt::PNG)
-               return g_strdup(MIME_TYPE_PNG);
-
-       return NULL;
-}
-
-static int __is_valid_picture_index(bool is_empty, unsigned int list_size, int index)
-{
-       metadata_editor_debug("list size [%d] picture index[%d]", list_size, index);
+       metadata_editor_debug("list size [%d] picture index[%d]", list_size, index);
 
        if (is_empty) {
                metadata_editor_error("No pictures in file");
@@ -1170,76 +877,79 @@ static int __get_APIC(ID3v2::Tag *tag, int index, void **picture, int *size, cha
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __get_mp3_picture(metadata_editor_s *metadata, int index, void **picture, int *size, char **mime_type)
-{
-       auto _file = dynamic_cast<MPEG::File*>(metadata->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);
-}
-
-static int __get_mp4_picture(metadata_editor_s *metadata, int index, void **picture, int *size, char **mime_type)
+static int __get_ogg_picture(Ogg::XiphComment *xtag, int index, void **picture, int *size, char **mime_type)
 {
        int ret = METADATA_EDITOR_ERROR_NONE;
 
-       auto tag = dynamic_cast<MP4::Tag*>(metadata->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;
-       }
+       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
 
-       auto lst = tag->item("covr").toCoverArtList();
+       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");
 
-       auto pictureFrame = static_cast<MP4::CoverArt>(lst[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");
+       int pictureSize = pictureFrame->data().size();
+       metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Size of picture is 0");
 
-       *picture = g_memdup(pictureFrame.data().data(), pictureSize);
+       *picture = g_memdup(pictureFrame->data().data(), pictureSize);
        *size = pictureSize;
-       *mime_type = __get_mime_type_from_cover_art(pictureFrame);
+       *mime_type = __get_mime_type(pictureFrame->mimeType());
 
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __get_flac_picture(metadata_editor_s *metadata, int index, void **picture, int *size, char **mime_type)
+static int __append_APIC(ID3v2::Tag *tag, const char *picture, size_t size, const char *mime_type)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
+       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
 
-       auto _file = dynamic_cast<FLAC::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       auto pictureFrame = new ID3v2::AttachedPictureFrame();
 
-       auto lst = _file->pictureList();
+       metadata_editor_info("New APIC frame will be added to the ID3v2 tag");
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+       pictureFrame->setPicture(ByteVector(picture, size));
+       pictureFrame->setType(ID3v2::AttachedPictureFrame::FrontCover);
+       pictureFrame->setMimeType(mime_type);
 
-       auto pictureFrame = static_cast<FLAC::Picture*>(lst[index]);
+       tag->addFrame(pictureFrame);
 
-       int pictureSize = pictureFrame->data().size();
-       metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
+       return METADATA_EDITOR_ERROR_NONE;
 
-       *picture = g_memdup(pictureFrame->data().data(), pictureSize);
-       *size = pictureSize;
-       *mime_type = __get_mime_type(pictureFrame->mimeType());
+}
+
+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");
+
+       auto frontCover = new FLAC::Picture;
+
+       frontCover->setData(ByteVector(picture, size));
+       frontCover->setType(FLAC::Picture::FrontCover);
+       frontCover->setMimeType(mime_type);
+
+       xtag->addPicture(frontCover);
 
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __get_wav_picture(metadata_editor_s *metadata, int index, void **picture, int *size, char **mime_type)
+static int __remove_APIC(ID3v2::Tag *tag, int index)
 {
-       auto _file = dynamic_cast<RIFF::WAV::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       int ret = METADATA_EDITOR_ERROR_NONE;
 
-       return __get_APIC(_file->tag(), index, picture, size, mime_type);
+       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");
+
+       tag->removeFrame(lst[index]);
+
+       return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __get_ogg_picture(Ogg::XiphComment *xtag, int index, void **picture, int *size, char **mime_type)
+static int __remove_ogg_picture(Ogg::XiphComment *xtag, int index)
 {
        int ret = METADATA_EDITOR_ERROR_NONE;
 
@@ -1250,99 +960,77 @@ static int __get_ogg_picture(Ogg::XiphComment *xtag, int index, void **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 pictureFrame = static_cast<FLAC::Picture*>(lst[index]);
-
-       int pictureSize = pictureFrame->data().size();
-       metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Size of picture is 0");
-
-       *picture = g_memdup(pictureFrame->data().data(), pictureSize);
-       *size = pictureSize;
-       *mime_type = __get_mime_type(pictureFrame->mimeType());
+       TagLib::List<TagLib::FLAC::Picture*>::Iterator it = lst.begin();
+       std::advance(it, index);
+       xtag->removePicture(*it, true);
 
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __get_ogg_vorbis_picture(metadata_editor_s *metadata, int index, void **picture, int *size, char **mime_type)
+
+int Mp3MetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
 {
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(metadata->file);
+       auto _file = dynamic_cast<MPEG::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);
+       return __append_APIC(_file->ID3v2Tag(true), picture, size, mime_type);
 }
 
-static int __get_ogg_flac_picture(metadata_editor_s *metadata, int index, void **picture, int *size, char **mime_type)
+int Mp3MetadataFile::getPicture(int index, void **picture, int *size, char **mime_type)
 {
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(metadata->file);
+       auto _file = dynamic_cast<MPEG::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);
+       return __get_APIC(_file->ID3v2Tag(), index, picture, size, mime_type);
 }
 
-extern "C" int metadata_editor_get_picture(metadata_editor_h metadata, int index, void **picture, int *size, char **mime_type)
+int Mp3MetadataFile::removePicture(int index)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
-       metadata_editor_s *_metadata = (metadata_editor_s*) metadata;
-
-       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(!picture, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture");
-       metadata_editor_retvm_if(!size, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid size");
-
-       metadata_editor_debug("file format [%d]", _metadata->filetype);
-
-       switch (_metadata->filetype) {
-       case METADATA_EDITOR_FORMAT_MP3:
-               return __get_mp3_picture(_metadata, index, picture, size, mime_type);
-
-       case METADATA_EDITOR_FORMAT_MP4:
-               return __get_mp4_picture(_metadata, index, picture, size, mime_type);
-
-       case METADATA_EDITOR_FORMAT_FLAC:
-               return __get_flac_picture(_metadata, index, picture, size, mime_type);
-
-       case METADATA_EDITOR_FORMAT_WAV:
-               return __get_wav_picture(_metadata, index, picture, size, mime_type);
-
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-               return __get_ogg_vorbis_picture(_metadata, index, picture, size, mime_type);
-
-       case METADATA_EDITOR_FORMAT_OGG_FLAC:
-               return __get_ogg_flac_picture(_metadata, index, picture, size, mime_type);
+       auto _file = dynamic_cast<MPEG::File*>(file);
+       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
 
-       default:
-               metadata_editor_error("Invalid file type [%d]", _metadata->filetype);
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
+       return __remove_APIC(_file->ID3v2Tag(true), index);
 }
 
-static int __append_APIC(ID3v2::Tag *tag, const char *picture, size_t size, const char *mime_type)
+int Mp3MetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
 {
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_METADATA_UPDATE_NOT_POSSIBLE, "Tag does not exist");
-
-       auto pictureFrame = new ID3v2::AttachedPictureFrame();
-
-       metadata_editor_info("New APIC frame will be added to the ID3v2 tag");
+       metadata_editor_retvm_if(file->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "File is readonly. Unable to modify");
 
-       pictureFrame->setPicture(ByteVector(picture, size));
-       pictureFrame->setType(ID3v2::AttachedPictureFrame::FrontCover);
-       pictureFrame->setMimeType(mime_type);
+       auto _file = dynamic_cast<MPEG::File*>(file);
+       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
 
-       tag->addFrame(pictureFrame);
+       return __set_ID3_tag(attribute, _file->ID3v1Tag(), _file->ID3v2Tag(true), value);
+}
 
-       return METADATA_EDITOR_ERROR_NONE;
+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);
 }
-static int __append_mp3_picture(metadata_editor_s *metadata, const char *picture ,size_t size, const char *mime_type)
+
+int Mp3MetadataFile::updateMetadata()
 {
-       auto _file = dynamic_cast<MPEG::File*>(metadata->file);
+       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);
+       auto tag1 = _file->ID3v1Tag();
+
+       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_OPERATION_FAILED;
 }
 
-static int __append_mp4_picture(metadata_editor_s *metadata, const char *picture, size_t size, const char *mime_type)
+int Mp4MetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
 {
-       auto tag = dynamic_cast<MP4::Tag*>(metadata->file->tag());
+       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;
@@ -1363,293 +1051,539 @@ static int __append_mp4_picture(metadata_editor_s *metadata, const char *picture
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __append_flac_picture(metadata_editor_s *metadata, const char *picture, size_t size, const char *mime_type)
+int Mp4MetadataFile::getPicture(int index, void **picture, int *size, char **mime_type)
 {
-       auto _file = dynamic_cast<FLAC::File*>(metadata->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);
+       int ret = METADATA_EDITOR_ERROR_NONE;
 
-       _file->addPicture(frontCover);
+       auto tag = dynamic_cast<MP4::Tag*>(file->tag());
+       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
 
-       return METADATA_EDITOR_ERROR_NONE;
-}
+       if (!(tag->contains("covr"))) {
+               metadata_editor_error("No item <covr> in file. No pictures in file");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
 
-static int __append_wav_picture(metadata_editor_s *metadata, const char *picture, size_t size, const char *mime_type)
-{
-       return __append_APIC(dynamic_cast<ID3v2::Tag*>(metadata->file->tag()), picture, size, mime_type);
-}
+       auto lst = tag->item("covr").toCoverArtList();
 
-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");
+       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
+       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
 
-       auto frontCover = new FLAC::Picture;
+       auto pictureFrame = static_cast<MP4::CoverArt>(lst[index]);
 
-       frontCover->setData(ByteVector(picture, size));
-       frontCover->setType(FLAC::Picture::FrontCover);
-       frontCover->setMimeType(mime_type);
+       int pictureSize = pictureFrame.data().size();
+       metadata_editor_retvm_if(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
 
-       xtag->addPicture(frontCover);
+       *picture = g_memdup(pictureFrame.data().data(), pictureSize);
+       *size = pictureSize;
+       *mime_type = __get_mime_type_from_cover_art(pictureFrame);
 
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __append_ogg_vorbis_picture(metadata_editor_s *metadata, const char *picture, size_t size, const char *mime_type)
+int Mp4MetadataFile::removePicture(int index)
 {
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(metadata->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 ret = METADATA_EDITOR_ERROR_NONE;
 
-static int __append_ogg_flac_picture(metadata_editor_s *metadata, const char *picture, size_t size, const char *mime_type)
-{
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(metadata->file);
-       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
+       auto tag = dynamic_cast<MP4::Tag*>(file->tag());
+       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
 
-       return __append_ogg_picture(_file->tag(), picture, size, mime_type);
-}
+       if (!(tag->contains("covr"))) {
+               metadata_editor_error("No item <covr> in file. No pictures in file");
+               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       }
 
-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;
-       metadata_editor_s *_metadata = (metadata_editor_s*) metadata;
+       auto lst = tag->item("covr").toCoverArtList();
 
-       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(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
+       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
+       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
 
-       ret = __check_file_validity(path);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid path");
+       auto picIt = lst.begin();
+       std::advance(picIt, index);
+       lst.erase(picIt);
 
-       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");
+       tag->setItem("covr", lst);      //?? FIX ME!
+
+       return METADATA_EDITOR_ERROR_NONE;
+}
 
-       metadata_editor_debug("file format [%d]", _metadata->filetype);
+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;
+       }
+}
 
-       switch (_metadata->filetype) {
-               case METADATA_EDITOR_FORMAT_MP3:
-                       ret = __append_mp3_picture(_metadata, picture, size, mime_type);
-                       break;
+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;
+       }
+}
 
-               case METADATA_EDITOR_FORMAT_MP4:
-                       ret = __append_mp4_picture(_metadata, picture, size, mime_type);
-                       break;
+int Mp4MetadataFile::updateMetadata()
+{
+       if (file->save())
+               return METADATA_EDITOR_ERROR_NONE;
 
-               case METADATA_EDITOR_FORMAT_FLAC:
-                       ret = __append_flac_picture(_metadata, picture, size, mime_type);
-                       break;
+       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+}
 
-               case METADATA_EDITOR_FORMAT_WAV:
-                       ret = __append_wav_picture(_metadata, picture, size, mime_type);
-                       break;
+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");
 
-               case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-                       ret = __append_ogg_vorbis_picture(_metadata, picture, size, mime_type);
-                       break;
+       auto frontCover = new FLAC::Picture;
 
-               case METADATA_EDITOR_FORMAT_OGG_FLAC:
-                       ret = __append_ogg_flac_picture(_metadata, picture, size, mime_type);
-                       break;
-               default: {
-                       metadata_editor_error("Invalid file type [%d]", _metadata->filetype);
-                       ret = METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-                       break;
-               }
-       }
+       frontCover->setData(ByteVector(picture, size));
+       frontCover->setType(FLAC::Picture::FrontCover);
+       frontCover->setMimeType(mime_type);
 
-       g_free(picture);
-       g_free(mime_type);
+       _file->addPicture(frontCover);
 
-       return ret;
+       return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __remove_APIC(ID3v2::Tag *tag, int index)
+int FlacMetadataFile::getPicture(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 _file = dynamic_cast<FLAC::File*>(file);
+       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
 
-       auto lst = tag->frameListMap()["APIC"];
+       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");
 
-       tag->removeFrame(lst[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_memdup(pictureFrame->data().data(), pictureSize);
+       *size = pictureSize;
+       *mime_type = __get_mime_type(pictureFrame->mimeType());
 
        return METADATA_EDITOR_ERROR_NONE;
 }
-static int __remove_mp3_picture(metadata_editor_s *metadata, int index)
+
+int FlacMetadataFile::removePicture(int index)
 {
-       auto _file = dynamic_cast<MPEG::File*>(metadata->file);
+       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");
 
-       return __remove_APIC(_file->ID3v2Tag(true), index);
+       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");
+
+       _file->removePicture(lst[index], true);
+
+       return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __remove_mp4_picture(metadata_editor_s *metadata, int index)
+int FlacMetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
 {
-       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 tag = dynamic_cast<MP4::Tag*>(metadata->file->tag());
-       metadata_editor_retvm_if(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
+       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");
 
-       if (!(tag->contains("covr"))) {
-               metadata_editor_error("No item <covr> in file. No pictures in file");
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       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;
        }
+}
 
-       auto lst = tag->item("covr").toCoverArtList();
+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");
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+       auto xtag = _file->xiphComment(false);
 
-       auto picIt = lst.begin();
-       std::advance(picIt, index);
-       lst.erase(picIt);
+       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;
+       }
+}
 
-       tag->setItem("covr", lst);      //?? FIX ME!
+int FlacMetadataFile::updateMetadata()
+{
+       if (file->save())
+               return METADATA_EDITOR_ERROR_NONE;
 
-       return METADATA_EDITOR_ERROR_NONE;
+       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
 }
 
-static int __remove_flac_picture(metadata_editor_s *metadata, int index)
+int OggVorbisMetadataFile::appendPicture(const char *picture ,size_t size, const char *mime_type)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
+       auto _file = dynamic_cast<Ogg::Vorbis::File*>(file);
+       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
 
-       auto _file = dynamic_cast<FLAC::File*>(metadata->file);
+       return __append_ogg_picture(_file->tag(), picture, size, mime_type);
+}
+
+int OggVorbisMetadataFile::getPicture(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");
 
-       auto lst = _file->pictureList();
+       return __get_ogg_picture(_file->tag(), index, picture, size, mime_type);
+}
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+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");
 
-       _file->removePicture(lst[index], true);
+       return __remove_ogg_picture(_file->tag(), index);
+}
 
-       return METADATA_EDITOR_ERROR_NONE;
+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 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);
 }
 
-static int __remove_wav_picture(metadata_editor_s *metadata, int index)
+int OggVorbisMetadataFile::getMetadata(metadata_editor_attr_e attribute, char **value)
 {
-       return __remove_APIC(dynamic_cast<ID3v2::Tag*>(metadata->file->tag()), index);
+       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_metadata(_file->tag(), attribute, value);
 }
 
-static int __remove_ogg_picture(Ogg::XiphComment *xtag, int index)
+int OggVorbisMetadataFile::updateMetadata()
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
+       if (file->save())
+               return METADATA_EDITOR_ERROR_NONE;
 
-       metadata_editor_retvm_if(!xtag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
+       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+}
 
-       auto lst = xtag->pictureList();
+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");
 
-       ret = __is_valid_picture_index(lst.isEmpty(), lst.size(), index);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid picture index");
+       return __append_ogg_picture(_file->tag(), picture, size, mime_type);
+}
 
-       TagLib::List<TagLib::FLAC::Picture*>::Iterator it = lst.begin();
-       std::advance(it, index);
-       xtag->removePicture(*it, true);
+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");
 
-       return METADATA_EDITOR_ERROR_NONE;
+       return __get_ogg_picture(_file->tag(), index, picture, size, mime_type);
 }
 
-static int __remove_ogg_vorbis_picture(metadata_editor_s *metadata, int index)
+int OggFlacMetadataFile::removePicture(int index)
 {
-       auto _file = dynamic_cast<Ogg::Vorbis::File*>(metadata->file);
+       auto _file = dynamic_cast<Ogg::FLAC::File*>(file);
        metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
 
        return __remove_ogg_picture(_file->tag(), index);
 }
 
-static int __remove_ogg_flac_picture(metadata_editor_s *metadata, int index)
+int OggFlacMetadataFile::setMetadata(metadata_editor_attr_e attribute, const char *value)
 {
-       auto _file = dynamic_cast<Ogg::FLAC::File*>(metadata->file);
+       auto _file = dynamic_cast<Ogg::FLAC::File*>(file);
        metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
 
-       return __remove_ogg_picture(_file->tag(), index);
+       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);
 }
 
-extern "C" int metadata_editor_remove_picture(metadata_editor_h metadata, int index)
+int OggFlacMetadataFile::getMetadata(metadata_editor_attr_e attribute, char **value)
 {
-       int ret = METADATA_EDITOR_ERROR_NONE;
-       metadata_editor_s *_metadata = (metadata_editor_s*) metadata;
+       auto _file = dynamic_cast<Ogg::FLAC::File*>(file);
+       metadata_editor_retvm_if(!_file, METADATA_EDITOR_ERROR_OPERATION_FAILED, "fail to dynamic_cast");
 
-       ret = __check_metadata_set_parameter(_metadata);
-       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_set_parameter() [%d]", ret);
+       return __get_ogg_metadata(_file->tag(), attribute, value);
+}
+
+int OggFlacMetadataFile::updateMetadata()
+{
+       if (file->save())
+               return METADATA_EDITOR_ERROR_NONE;
 
-       metadata_editor_debug("file format [%d]", _metadata->filetype);
+       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+}
 
-       switch (_metadata->filetype) {
-               case METADATA_EDITOR_FORMAT_MP3:
-                       return __remove_mp3_picture(_metadata, index);
+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);
+}
+
+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");
 
-               case METADATA_EDITOR_FORMAT_MP4:
-                       return __remove_mp4_picture(_metadata, index);
+       return __get_APIC(_file->tag(), index, picture, size, mime_type);
+}
 
-               case METADATA_EDITOR_FORMAT_FLAC:
-                       return __remove_flac_picture(_metadata, index);
+int WavMetadataFile::removePicture(int index)
+{
+       return __remove_APIC(dynamic_cast<ID3v2::Tag*>(file->tag()), index);
+}
 
-               case METADATA_EDITOR_FORMAT_WAV:
-                       return __remove_wav_picture(_metadata, index);
+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");
 
-               case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-                       return __remove_ogg_vorbis_picture(_metadata, index);
+       return __set_ID3_tag(attribute, NULL, _file->tag(), value);
+}
 
-               case METADATA_EDITOR_FORMAT_OGG_FLAC:
-                       return __remove_ogg_flac_picture(_metadata, index);
+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");
 
-               default:
-                       metadata_editor_error("Invalid file type [%d]", _metadata->filetype);
-                       return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
-       }
+       return __get_ID3_tag(attribute, NULL, _file->tag(), value);
+}
+
+int WavMetadataFile::updateMetadata()
+{
+       if (file->save())
+               return METADATA_EDITOR_ERROR_NONE;
+
+       return METADATA_EDITOR_ERROR_OPERATION_FAILED;
+}
+
+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));
+       memset(_metadata, 0, sizeof(metadata_editor_s));
+
+       *metadata = (metadata_editor_h)_metadata;
+
+       return METADATA_EDITOR_ERROR_NONE;
 }
 
 extern "C" int metadata_editor_destroy(metadata_editor_h metadata)
 {
-       metadata_editor_s *_metadata = (metadata_editor_s*)metadata;
+       auto _metadata = static_cast<metadata_editor_s*>(metadata);
        metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
 
-       metadata_editor_debug("file format [%d]", _metadata->filetype);
+       delete _metadata->intf;
+       free(_metadata);
 
-       switch (_metadata->filetype) {
-       case METADATA_EDITOR_FORMAT_MP3:
-               delete dynamic_cast<TagLib::MPEG::File*>(_metadata->file);
-               break;
+       return METADATA_EDITOR_ERROR_NONE;
+}
 
-       case METADATA_EDITOR_FORMAT_MP4:
-               delete dynamic_cast<TagLib::MP4::File*>(_metadata->file);
-               break;
+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;
+       auto _metadata = static_cast<metadata_editor_s*>(metadata);
 
-       case METADATA_EDITOR_FORMAT_FLAC:
-               delete dynamic_cast<TagLib::FLAC::File*>(_metadata->file);
-               break;
+       metadata_editor_debug_fenter();
 
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS:
-               delete dynamic_cast<TagLib::Ogg::Vorbis::File*>(_metadata->file);
-               break;
+       metadata_editor_retvm_if(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
 
-       case METADATA_EDITOR_FORMAT_OGG_FLAC:
-               delete dynamic_cast<TagLib::Ogg::FLAC::File*>(_metadata->file);
-               break;
+       ret = __check_file_validity(path);
+       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid path");
 
-       case METADATA_EDITOR_FORMAT_WAV:
-               delete dynamic_cast<TagLib::RIFF::WAV::File*>(_metadata->file);
-               break;
+       media_type = __metadata_editor_get_file_type(path);
 
-       default:
-               metadata_editor_error("Wrong file type");
-               return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
+       if (_metadata->intf) {
+               metadata_editor_info("file free [%p]", _metadata->intf);
+               delete _metadata->intf;
        }
 
-       g_free(_metadata);
+       metadata_editor_debug("media_type : [%d]", 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;
+               }
+       } catch (const std::bad_alloc &ex) {
+               metadata_editor_retvm_if(!_metadata->intf, METADATA_EDITOR_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
+       }
+
+       if (!_metadata->intf->isOpen()) {
+               delete _metadata->intf;
+               _metadata->intf = nullptr;
+               return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+       }
 
        return METADATA_EDITOR_ERROR_NONE;
 }
+
+extern "C" int metadata_editor_append_picture(metadata_editor_h metadata, const char *path)
+{
+       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(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
+
+       ret = __check_file_validity(path);
+       metadata_editor_retvm_if(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid path");
+
+       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);
+
+       g_free(picture);
+       g_free(mime_type);
+
+       return ret;
+}
+
+extern "C" int metadata_editor_remove_picture(metadata_editor_h metadata, int index)
+{
+       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);
+
+       return _metadata->intf->removePicture(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(!picture, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture");
+       metadata_editor_retvm_if(!size, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid size");
+
+       return _metadata->intf->getPicture(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);
+
+       return _metadata->intf->setMetadata(attribute, value);
+}
+
+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(ret != METADATA_EDITOR_ERROR_NONE, ret, "fail to __check_metadata_get_parameter() [%d]", ret);
+
+       return _metadata->intf->getMetadata(attribute, value);
+}
+
+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);
+
+       return _metadata->intf->updateMetadata();
+}