Picture-related code refactoring 11/277511/5 submit/tizen/20220711.084601
authorminje.ahn <minje.ahn@samsung.com>
Fri, 8 Jul 2022 02:15:59 +0000 (11:15 +0900)
committerminje.ahn <minje.ahn@samsung.com>
Mon, 11 Jul 2022 06:25:47 +0000 (15:25 +0900)
Change-Id: I7bbdbec206c1363f9a8df57ae166ecc52492b836
Signed-off-by: minje.ahn <minje.ahn@samsung.com>
include/metadata_editor_private.h
src/metadata_editor.cpp

index 8220a7218cfc128b88c978da7c41af1635259161..d194f1836b8cf8b931e64293708ddd0f34ef5e30 100755 (executable)
@@ -58,6 +58,12 @@ extern "C" {
                        } \
                } while (0)
 
+#define ME_RETV_IF(expr, val) do { \
+                       if ((expr)) { \
+                               return (val); \
+                       } \
+               } while (0)
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 6ed0b011497e46ad12711b2016fd73683ec12842..bcda6e48d8f01bf044fc18779d07194880beed7a 100755 (executable)
@@ -39,21 +39,6 @@ using namespace TagLib;
 #define MIME_TYPE_JPEG "image/jpeg"
 #define MIME_TYPE_PNG "image/png"
 
-typedef enum {
-       METADATA_EDITOR_FORMAT_MP3 = 0,                 /**< MP3 File */
-       METADATA_EDITOR_FORMAT_MP4,                             /**< MP4 File */
-       METADATA_EDITOR_FORMAT_FLAC,                            /**< FLAC File */
-       METADATA_EDITOR_FORMAT_OGG_VORBIS,                      /**< Vorbis Audio in Ogg container */
-       METADATA_EDITOR_FORMAT_OGG_FLAC,                        /**< FLAC Audio in Ogg container */
-       METADATA_EDITOR_FORMAT_WAV,                             /**< WAV file */
-       METADATA_EDITOR_FORMAT_NOTYPE = 0xFF            /**< Error type. File type is not correct or not specified */
-} metadata_editor_format_e;
-
-typedef struct {
-       FileRef *fref;
-       metadata_editor_format_e format;
-} metadata_editor_s;
-
 static String __get_file_ext(const char *file_path)
 {
        String s = String(file_path, String::UTF8);
@@ -63,24 +48,6 @@ static String __get_file_ext(const char *file_path)
        return "";
 }
 
-static metadata_editor_format_e __get_format(File *f)
-{
-       if (dynamic_cast<MPEG::File *>(f))
-               return METADATA_EDITOR_FORMAT_MP3;
-       else if (dynamic_cast<MP4::File *>(f))
-               return METADATA_EDITOR_FORMAT_MP4;
-       else if (dynamic_cast<FLAC::File *>(f))
-               return METADATA_EDITOR_FORMAT_FLAC;
-       else if (dynamic_cast<RIFF::WAV::File *>(f))
-               return METADATA_EDITOR_FORMAT_WAV;
-       else if (dynamic_cast<Ogg::Vorbis::File *>(f))
-               return METADATA_EDITOR_FORMAT_OGG_VORBIS;
-       else if (dynamic_cast<Ogg::FLAC::File *>(f))
-               return METADATA_EDITOR_FORMAT_OGG_FLAC;
-       else
-               return METADATA_EDITOR_FORMAT_NOTYPE;
-}
-
 static const String __get_picture_type(const char *path)
 {
        String ext = __get_file_ext(path);
@@ -118,49 +85,12 @@ private:
        TagLib::FileStream stream;
 };
 
-static int __check_file_validity(const char *path)
+template <class T>
+static bool __is_valid_index(const List<T>& lst, int index)
 {
-       ME_RETVM_IF(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
-       ME_SDBG("path : [%s]", path);
-
-       if (access(path, R_OK) < 0) {
-               if (errno == EACCES || errno == EPERM) {
-                       ME_ERR("Permission denied");
-                       return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
-               }
-
-               ME_ERR("Fail to open path");
-               return METADATA_EDITOR_ERROR_FILE_EXISTS;
-       }
-
-       return METADATA_EDITOR_ERROR_NONE;
-}
-
-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)
-{
-       ME_DBG("list size [%d] picture index[%d]", list_size, index);
-       ME_RETVM_IF(is_empty, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "No picture");
-       ME_RETVM_IF((index < 0) || (list_size <= (uint)index), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Out of range");
-
-       return METADATA_EDITOR_ERROR_NONE;
+       ME_RETVM_IF(lst.isEmpty(), false, "No picture");
+       ME_RETVM_IF((index < 0) || (lst.size() <= static_cast<uint>(index)), false, "Out of range:size[%d] index[%d]", lst.size(), index);
+       return true;
 }
 
 static int __get_APIC(ID3v2::Tag *tag, int index, void **picture, int *size, char **mime_type)
@@ -168,8 +98,7 @@ static int __get_APIC(ID3v2::Tag *tag, int index, void **picture, int *size, cha
        ME_RETVM_IF(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Tag does not exist");
 
        auto lst = tag->frameListMap()["APIC"];
-
-       ME_RETVM_IF(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
+       ME_RETV_IF(!__is_valid_index(lst, index), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
        auto pictureFrame = static_cast<ID3v2::AttachedPictureFrame*>(lst[index]);
 
@@ -178,7 +107,7 @@ static int __get_APIC(ID3v2::Tag *tag, int index, void **picture, int *size, cha
 
        *picture = g_memdup2(pictureFrame->picture().data(), pictureSize);
        *size = pictureSize;
-       *mime_type = __get_mime_type(pictureFrame->mimeType());
+       *mime_type = g_strdup(pictureFrame->mimeType().toCString());
 
        return METADATA_EDITOR_ERROR_NONE;
 }
@@ -188,8 +117,7 @@ static int __get_ogg_picture(Ogg::XiphComment *xtag, int index, void **picture,
        ME_RETVM_IF(!xtag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid XiphComment");
 
        auto lst = xtag->pictureList();
-
-       ME_RETVM_IF(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
+       ME_RETV_IF(!__is_valid_index(lst, index), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
        auto pictureFrame = static_cast<FLAC::Picture*>(lst[index]);
 
@@ -198,7 +126,7 @@ static int __get_ogg_picture(Ogg::XiphComment *xtag, int index, void **picture,
 
        *picture = g_memdup2(pictureFrame->data().data(), pictureSize);
        *size = pictureSize;
-       *mime_type = __get_mime_type(pictureFrame->mimeType());
+       *mime_type = g_strdup(pictureFrame->mimeType().toCString());
 
        return METADATA_EDITOR_ERROR_NONE;
 }
@@ -232,8 +160,7 @@ static int __remove_APIC(ID3v2::Tag *tag, int index)
        ME_RETVM_IF(!tag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid ID3v2");
 
        auto lst = tag->frameListMap()["APIC"];
-
-       ME_RETVM_IF(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
+       ME_RETV_IF(!__is_valid_index(lst, index), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
        tag->removeFrame(lst[index]);
 
@@ -245,8 +172,7 @@ static int __remove_ogg_picture(Ogg::XiphComment *xtag, int index)
        ME_RETVM_IF(!xtag, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid XiphComment");
 
        auto lst = xtag->pictureList();
-
-       ME_RETVM_IF(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
+       ME_RETV_IF(!__is_valid_index(lst, index), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
        TagLib::List<TagLib::FLAC::Picture*>::Iterator it = lst.begin();
        std::advance(it, index);
@@ -255,246 +181,240 @@ static int __remove_ogg_picture(Ogg::XiphComment *xtag, int index)
        return METADATA_EDITOR_ERROR_NONE;
 }
 
-static int __append_picture(File *f, metadata_editor_format_e format, const char *path)
+class IAlbumArt
 {
-       ME_RETVM_IF(!f, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-
-       PictureFrame pic(path);
-       ME_RETVM_IF(!pic.opened(), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture");
+public:
+       virtual ~IAlbumArt() = default;
+       virtual int append(PictureFrame &pic) = 0;
+       virtual int remove(int index) = 0;
+       virtual int read(int index, void **picture, int *size, char **mime_type) = 0;
+       virtual uint count() = 0;
+};
 
-       switch (format) {
-       case METADATA_EDITOR_FORMAT_MP3: {
-               auto _file = dynamic_cast<MPEG::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __append_APIC(_file->ID3v2Tag(true), pic);
+class Mp3AlbumArt : public IAlbumArt {
+public:
+       explicit Mp3AlbumArt(FileRef *fileref) {
+               file = dynamic_cast<MPEG::File *>(fileref->file());
        }
-       case METADATA_EDITOR_FORMAT_MP4: {
-               auto _file = dynamic_cast<MP4::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               MP4::CoverArtList lst;
-
-               if (_file->tag()->contains("covr")) {
-                       ME_INFO("The item <covr> exists. Adding picture");
-                       lst = _file->tag()->item("covr").toCoverArtList();
-               }
+       ~Mp3AlbumArt() override {};
 
-               lst.append(MP4::CoverArt(pic.mp4format(), pic.data()));
-               _file->tag()->setItem("covr", lst);
-
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-       case METADATA_EDITOR_FORMAT_FLAC: {
-               auto _file = dynamic_cast<FLAC::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               auto frontCover = new FLAC::Picture;
-               frontCover->setData(pic.data());
-               frontCover->setMimeType(pic.mime());
-               _file->addPicture(frontCover);
-               return METADATA_EDITOR_ERROR_NONE;
-       }
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
-               auto _file = dynamic_cast<Ogg::Vorbis::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __append_ogg_picture(_file->tag(), pic);
+       int append(PictureFrame &pic) override {
+               return __append_APIC(file->ID3v2Tag(true), pic);
        }
-       case METADATA_EDITOR_FORMAT_OGG_FLAC: {
-               auto _file = dynamic_cast<Ogg::FLAC::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __append_ogg_picture(_file->tag(), pic);
+       int remove(int index) override {
+               return __remove_APIC(file->ID3v2Tag(), index);
        }
-       case METADATA_EDITOR_FORMAT_WAV: {
-               auto _file = dynamic_cast<RIFF::WAV::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __append_APIC(dynamic_cast<ID3v2::Tag*>(_file->tag()), pic);
+       int read(int index, void **picture, int *size, char **mime_type) override {
+               return __get_APIC(file->ID3v2Tag(), index, picture, size, mime_type);
        }
-       default:
-               return METADATA_EDITOR_ERROR_NONE;
+       uint count() override {
+               return file->ID3v2Tag() ? file->ID3v2Tag()->frameListMap()["APIC"].size() : 0;
        }
-}
-
-static int __remove_picture(File *f, metadata_editor_format_e format, int index)
-{
-       ME_RETVM_IF(!f, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
+private:
+       MPEG::File *file;
+};
 
-       switch (format) {
-       case METADATA_EDITOR_FORMAT_MP3: {
-               auto _file = dynamic_cast<MPEG::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __remove_APIC(_file->ID3v2Tag(true), index);
+class Mp4AlbumArt : public IAlbumArt {
+public:
+       explicit Mp4AlbumArt(FileRef *fileref) {
+               file = dynamic_cast<MP4::File *>(fileref->file());
        }
-       case METADATA_EDITOR_FORMAT_MP4: {
-               auto _file = dynamic_cast<MP4::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               auto tag = dynamic_cast<MP4::Tag*>(_file->tag());
+       ~Mp4AlbumArt() override {};
 
-               ME_RETVM_IF(!(tag->contains("covr")), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "No picture");
+       int append(PictureFrame &pic) override {
+               MP4::CoverArtList lst;
 
-               auto lst = tag->item("covr").toCoverArtList();
+               if (file->tag()->contains("covr")) {
+                       ME_INFO("The item <covr> exists. Adding picture");
+                       lst = file->tag()->item("covr").toCoverArtList();
+               }
 
-               ME_RETVM_IF(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
+               lst.append(MP4::CoverArt(pic.mp4format(), pic.data()));
+               file->tag()->setItem("covr", lst);
+
+               return METADATA_EDITOR_ERROR_NONE;
+       }
+       int remove(int index) override {
+               ME_RETVM_IF(!(file->tag()->contains("covr")), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "No picture");
+               auto lst = file->tag()->item("covr").toCoverArtList();
+               ME_RETV_IF(!__is_valid_index(lst, index), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
                auto picIt = lst.begin();
                std::advance(picIt, index);
                lst.erase(picIt);
 
-               tag->setItem("covr", lst);      //?? FIX ME!
+               file->tag()->setItem("covr", lst);      //?? FIX ME!
 
                return METADATA_EDITOR_ERROR_NONE;
        }
-       case METADATA_EDITOR_FORMAT_FLAC: {
-               auto _file = dynamic_cast<FLAC::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               auto lst = _file->pictureList();
+       int read(int index, void **picture, int *size, char **mime_type) override {
+               ME_RETVM_IF(!(file->tag()->contains("covr")), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "No picture");
+               auto lst = file->tag()->item("covr").toCoverArtList();
+               ME_RETV_IF(!__is_valid_index(lst, index), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
+
+               auto coverArt = static_cast<MP4::CoverArt>(lst[index]);
+               int coverArtSize = coverArt.data().size();
+               ME_RETVM_IF(coverArtSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
 
-               ME_RETVM_IF(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
+               *picture = g_memdup2(coverArt.data().data(), coverArtSize);
+               *size = coverArtSize;
+               if (coverArt.format() == MP4::CoverArt::JPEG)
+                       *mime_type = g_strdup(MIME_TYPE_JPEG);
+               else if (coverArt.format() == MP4::CoverArt::PNG)
+                       *mime_type = g_strdup(MIME_TYPE_PNG);
 
-               _file->removePicture(lst[index], true);
                return METADATA_EDITOR_ERROR_NONE;
        }
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
-               auto _file = dynamic_cast<Ogg::Vorbis::File *>(f);
-               ME_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);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __remove_ogg_picture(_file->tag(), index);
+       uint count() override {
+               return (file->tag() && file->tag()->contains("covr")) ? file->tag()->item("covr").toCoverArtList().size() : 0;
        }
-       case METADATA_EDITOR_FORMAT_WAV: {
-               auto _file = dynamic_cast<RIFF::WAV::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __remove_APIC(dynamic_cast<ID3v2::Tag*>(_file->tag()), index);
+private:
+       MP4::File *file;
+};
+
+class FlacAlbumArt : public IAlbumArt {
+public:
+       explicit FlacAlbumArt(FileRef *fileref) {
+               file = dynamic_cast<FLAC::File *>(fileref->file());
        }
-       default:
+       ~FlacAlbumArt() override {};
+
+       int append(PictureFrame &pic) override {
+               auto frontCover = new FLAC::Picture;
+               frontCover->setData(pic.data());
+               frontCover->setMimeType(pic.mime());
+               file->addPicture(frontCover);
                return METADATA_EDITOR_ERROR_NONE;
        }
-}
-
-static int __get_picture(File *f, metadata_editor_format_e format, int index, void **picture, int *size, char **mime_type)
-{
-       ME_RETVM_IF(!f, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-       ME_RETVM_IF(!picture, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture");
-       ME_RETVM_IF(!size, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid size");
-       ME_RETVM_IF(!mime_type, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid mime_type");
+       int remove(int index) override {
+               auto lst = file->pictureList();
+               ME_RETV_IF(!__is_valid_index(lst, index), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
-       switch (format) {
-       case METADATA_EDITOR_FORMAT_MP3: {
-               auto _file = dynamic_cast<MPEG::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __get_APIC(_file->ID3v2Tag(), index, picture, size, mime_type);
+               file->removePicture(lst[index], true);
+               return METADATA_EDITOR_ERROR_NONE;
        }
-       case METADATA_EDITOR_FORMAT_MP4: {
-               auto _file = dynamic_cast<MP4::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               auto tag = dynamic_cast<MP4::Tag *>(_file->tag());
-
-               ME_RETVM_IF(!(tag->contains("covr")), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "No picture");
-
-               auto lst = tag->item("covr").toCoverArtList();
+       int read(int index, void **picture, int *size, char **mime_type) override {
+               auto lst = file->pictureList();
+               ME_RETV_IF(!__is_valid_index(lst, index), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
-               ME_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<MP4::CoverArt>(lst[index]);
-
-               int pictureSize = pictureFrame.data().size();
+               auto pictureFrame = static_cast<FLAC::Picture*>(lst[index]);
+               int pictureSize = pictureFrame->data().size();
                ME_RETVM_IF(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
 
-               *picture = g_memdup2(pictureFrame.data().data(), pictureSize);
+               *picture = g_memdup2(pictureFrame->data().data(), pictureSize);
                *size = pictureSize;
-               *mime_type = __get_mime_type_from_cover_art(pictureFrame);
+               *mime_type = g_strdup(pictureFrame->mimeType().toCString());
 
                return METADATA_EDITOR_ERROR_NONE;
        }
-       case METADATA_EDITOR_FORMAT_FLAC: {
-               auto _file = dynamic_cast<FLAC::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               auto lst = _file->pictureList();
+       uint count() override {
+               return file->pictureList().size();
+       }
+private:
+       FLAC::File *file;
+};
 
-               ME_RETVM_IF(__is_valid_picture_index(lst.isEmpty(), lst.size(), index) != METADATA_EDITOR_ERROR_NONE, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture index");
+class OggVorbisAlbumArt : public IAlbumArt {
+public:
+       explicit OggVorbisAlbumArt(FileRef *fileref) {
+               file = dynamic_cast<Ogg::Vorbis::File *>(fileref->file());
+       }
+       ~OggVorbisAlbumArt() override {};
 
-               auto pictureFrame = static_cast<FLAC::Picture*>(lst[index]);
+       int append(PictureFrame &pic) override {
+               return __append_ogg_picture(file->tag(), pic);
+       }
+       int remove(int index) override {
+               return __remove_ogg_picture(file->tag(), index);
+       }
+       int read(int index, void **picture, int *size, char **mime_type) override {
+               return __get_ogg_picture(file->tag(), index, picture, size, mime_type);
+       }
+       uint count() override {
+               return file->tag() ? file->tag()->pictureList().size() : 0;
+       }
+private:
+       Ogg::Vorbis::File *file;
+};
 
-               int pictureSize = pictureFrame->data().size();
-               ME_RETVM_IF(pictureSize == 0, METADATA_EDITOR_ERROR_OPERATION_FAILED, "Size of picture is 0");
+class OggFlacAlbumArt : public IAlbumArt {
+public:
+       explicit OggFlacAlbumArt(FileRef *fileref) {
+               file = dynamic_cast<Ogg::FLAC::File *>(fileref->file());
+       }
+       ~OggFlacAlbumArt() override {};
 
-               *picture = g_memdup2(pictureFrame->data().data(), pictureSize);
-               *size = pictureSize;
-               *mime_type = __get_mime_type(pictureFrame->mimeType());
+       int append(PictureFrame &pic) override {
+               return __append_ogg_picture(file->tag(), pic);
+       }
+       int remove(int index) override {
+               return __remove_ogg_picture(file->tag(), index);
+       }
+       int read(int index, void **picture, int *size, char **mime_type) override {
+               return __get_ogg_picture(file->tag(), index, picture, size, mime_type);
+       }
+       uint count() override {
+               return file->tag() ? file->tag()->pictureList().size() : 0;
+       }
+private:
+       Ogg::FLAC::File *file;
+};
 
-               return METADATA_EDITOR_ERROR_NONE;
+class WavAlbumArt : public IAlbumArt {
+public:
+       explicit WavAlbumArt(FileRef *fileref) {
+               file = dynamic_cast<RIFF::WAV::File *>(fileref->file());
        }
-       case METADATA_EDITOR_FORMAT_OGG_VORBIS: {
-               auto _file = dynamic_cast<Ogg::Vorbis::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __get_ogg_picture(_file->tag(), index, picture, size, mime_type);
+       ~WavAlbumArt() override {};
+
+       int append(PictureFrame &pic) override {
+               return __append_APIC(file->tag(), pic);
        }
-       case METADATA_EDITOR_FORMAT_OGG_FLAC: {
-               auto _file = dynamic_cast<Ogg::FLAC::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __get_ogg_picture(_file->tag(), index, picture, size, mime_type);
+       int remove(int index) override {
+               return __remove_APIC(file->tag(), index);
        }
-       case METADATA_EDITOR_FORMAT_WAV:{
-               auto _file = dynamic_cast<RIFF::WAV::File *>(f);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               return __get_APIC(_file->tag(), index, picture, size, mime_type);
+       int read(int index, void **picture, int *size, char **mime_type) override {
+               return __get_APIC(file->tag(), index, picture, size, mime_type);
        }
-       default:
-               return METADATA_EDITOR_ERROR_NONE;
+       uint count() override {
+               return file->tag() ? file->tag()->frameListMap()["APIC"].size() : 0;
        }
-}
+private:
+       RIFF::WAV::File *file;
+};
 
-static int __get_picture_number(File *f, metadata_editor_format_e format, char **value)
+typedef struct _metadata_editor_s {
+       FileRef *fref;
+       IAlbumArt *ifart;
+} metadata_editor_s;
+
+static int __check_file_validity(const char *path)
 {
-       ME_RETVM_IF(!f, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-       ME_RETVM_IF(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
+       ME_RETVM_IF(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
+       ME_SDBG("path : [%s]", path);
 
-       switch (format) {
-       case METADATA_EDITOR_FORMAT_MP3: {
-               auto _file = dynamic_cast<MPEG::File *>(f);
-               ME_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);
-               ME_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("0");
-               break;
-       }
-       case METADATA_EDITOR_FORMAT_FLAC: {
-               auto _file = dynamic_cast<FLAC::File *>(f);
-               *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);
-               ME_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);
-               ME_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);
-               ME_RETVM_IF(!_file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
-               *value = g_strdup_printf("%u", _file->tag() ? _file->tag()->frameListMap()["APIC"].size() : 0);
-               break;
-       }
-       default:
-               break;
+       if (access(path, R_OK) < 0) {
+               if (errno == EACCES || errno == EPERM) {
+                       ME_ERR("Permission denied");
+                       return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
+               }
+
+               ME_ERR("Fail to open path");
+               return METADATA_EDITOR_ERROR_FILE_EXISTS;
        }
 
        return METADATA_EDITOR_ERROR_NONE;
 }
 
+static int __is_valid_handle(metadata_editor_s *metadata, bool isWritable)
+{
+       ME_RETVM_IF(!metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
+       ME_RETVM_IF(!metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       ME_RETVM_IF(isWritable && metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
+       ME_RETVM_IF(!metadata->ifart, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid tag");
+       return METADATA_EDITOR_ERROR_NONE;
+}
+
 static int __set_to_property_map(File *file, String key, const char *value)
 {
        ME_RETVM_IF(!file, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid file");
@@ -560,6 +480,7 @@ extern "C" int metadata_editor_destroy(metadata_editor_h metadata)
        ME_RETVM_IF(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
 
        delete _metadata->fref;
+       delete _metadata->ifart;
        free(_metadata);
 
        return METADATA_EDITOR_ERROR_NONE;
@@ -568,9 +489,7 @@ 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;
-       metadata_editor_format_e media_type = METADATA_EDITOR_FORMAT_NOTYPE;
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
-
        ME_RETVM_IF(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
 
        ret = __check_file_validity(path);
@@ -579,6 +498,8 @@ extern "C" int metadata_editor_set_path(metadata_editor_h metadata, const char *
        if (_metadata->fref) {
                ME_INFO("file free [%p]", _metadata->fref);
                delete _metadata->fref;
+               if (_metadata->ifart)
+                       delete _metadata->ifart;
        }
 
        try {
@@ -596,15 +517,18 @@ extern "C" int metadata_editor_set_path(metadata_editor_h metadata, const char *
                return METADATA_EDITOR_ERROR_PERMISSION_DENIED;
        }
 
-       media_type = __get_format(_metadata->fref->file());
-       if (media_type == METADATA_EDITOR_FORMAT_NOTYPE) {
-               delete _metadata->fref;
-               _metadata->fref = nullptr;
-               return METADATA_EDITOR_ERROR_NOT_SUPPORTED;
-       }
-
-       ME_DBG("media_type : [%d]", media_type);
-       _metadata->format = media_type;
+       if (dynamic_cast<MPEG::File *>(_metadata->fref->file()))
+               _metadata->ifart = new Mp3AlbumArt(_metadata->fref);
+       else if (dynamic_cast<MP4::File *>(_metadata->fref->file()))
+               _metadata->ifart = new Mp4AlbumArt(_metadata->fref);
+       else if (dynamic_cast<FLAC::File *>(_metadata->fref->file()))
+               _metadata->ifart = new FlacAlbumArt(_metadata->fref);
+       else if (dynamic_cast<RIFF::WAV::File *>(_metadata->fref->file()))
+               _metadata->ifart = new WavAlbumArt(_metadata->fref);
+       else if (dynamic_cast<Ogg::Vorbis::File *>(_metadata->fref->file()))
+               _metadata->ifart = new OggVorbisAlbumArt(_metadata->fref);
+       else if (dynamic_cast<Ogg::FLAC::File *>(_metadata->fref->file()))
+               _metadata->ifart = new OggFlacAlbumArt(_metadata->fref);
 
        return METADATA_EDITOR_ERROR_NONE;
 }
@@ -613,49 +537,39 @@ extern "C" int metadata_editor_append_picture(metadata_editor_h metadata, const
 {
        int ret = METADATA_EDITOR_ERROR_NONE;
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
-
-       ME_RETVM_IF(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-       ME_RETVM_IF(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
-       ME_RETVM_IF(_metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
-       ME_RETVM_IF(!path, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
+       ME_RETV_IF(__is_valid_handle(_metadata, true), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
        ret = __check_file_validity(path);
        ME_RETVM_IF(ret != METADATA_EDITOR_ERROR_NONE, ret, "Invalid path");
+       PictureFrame pic(path);
+       ME_RETVM_IF(!pic.opened(), METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid path");
 
-       return __append_picture(_metadata->fref->file(), _metadata->format, path);
+       return _metadata->ifart->append(pic);
 }
 
 extern "C" int metadata_editor_remove_picture(metadata_editor_h metadata, int index)
 {
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
+       ME_RETV_IF(__is_valid_handle(_metadata, true), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
-       ME_RETVM_IF(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-       ME_RETVM_IF(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
-       ME_RETVM_IF(_metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
-
-       return __remove_picture(_metadata->fref->file(), _metadata->format, index);
+       return _metadata->ifart->remove(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);
-
-       ME_RETVM_IF(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-       ME_RETVM_IF(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       ME_RETV_IF(__is_valid_handle(_metadata, false), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
        ME_RETVM_IF(!picture, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid picture");
        ME_RETVM_IF(!size, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid size");
        ME_RETVM_IF(!mime_type, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid mime_type");
 
-       return __get_picture(_metadata->fref->file(), _metadata->format, index, picture, size, mime_type);
+       return _metadata->ifart->read(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);
-
-       ME_RETVM_IF(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-       ME_RETVM_IF(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
-       ME_RETVM_IF(_metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
+       ME_RETV_IF(__is_valid_handle(_metadata, true), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
        switch (attribute) {
        case METADATA_EDITOR_ATTR_ARTIST:
@@ -691,9 +605,7 @@ extern "C" int metadata_editor_set_metadata(metadata_editor_h metadata, metadata
 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);
-
-       ME_RETVM_IF(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-       ME_RETVM_IF(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
+       ME_RETV_IF(__is_valid_handle(_metadata, false), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
        ME_RETVM_IF(!value, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid value");
 
        PropertyMap tags = _metadata->fref->file()->properties();
@@ -724,7 +636,8 @@ extern "C" int metadata_editor_get_metadata(metadata_editor_h metadata, metadata
        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);
+               *value = g_strdup_printf("%u", _metadata->ifart->count());
+               return METADATA_EDITOR_ERROR_NONE;
        default:
                ME_ERR("Invalid attribute [%d]", attribute);
                return METADATA_EDITOR_ERROR_INVALID_PARAMETER;
@@ -734,10 +647,7 @@ extern "C" int metadata_editor_get_metadata(metadata_editor_h metadata, metadata
 extern "C" int metadata_editor_update_metadata(metadata_editor_h metadata)
 {
        auto _metadata = static_cast<metadata_editor_s*>(metadata);
-
-       ME_RETVM_IF(!_metadata, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "Invalid metadata");
-       ME_RETVM_IF(!_metadata->fref, METADATA_EDITOR_ERROR_INVALID_PARAMETER, "File loading fail");
-       ME_RETVM_IF(_metadata->fref->file()->readOnly(), METADATA_EDITOR_ERROR_PERMISSION_DENIED, "Readonly error");
+       ME_RETV_IF(__is_valid_handle(_metadata, true), METADATA_EDITOR_ERROR_INVALID_PARAMETER);
 
        if (!_metadata->fref->file()->save())
                return METADATA_EDITOR_ERROR_OPERATION_FAILED;