https://github.com/gogglesmm/gogglesmm/commit/abd6ec6b8270feb1841a97f9be5364541f4a939c.patch
https://github.com/gogglesmm/gogglesmm/commit/9f7110b0950a2862016e18163b9c2737a2a935d6.patch

diff --git a/src/GMAbout.cpp b/src/GMAbout.cpp
index eb2c565..0b625cb 100644
--- a/src/GMAbout.cpp
+++ b/src/GMAbout.cpp
@@ -27,7 +27,6 @@
 #endif
 #include <FXPNGIcon.h>
 #include <sqlite3.h>
-#include <tag.h>
 
 #define UTF8_COPYRIGHT_SIGN "\xc2\xa9"
 
diff --git a/src/GMTag.cpp b/src/GMTag.cpp
index 2add466..a32ce46 100644
--- a/src/GMTag.cpp
+++ b/src/GMTag.cpp
@@ -26,9 +26,9 @@
 #include "GMTag.h"
 #include "GMAudioPlayer.h"
 
-/// TagLib
-
 
+// taglib Variant enum Type { Bool } conflicts with Xlib
+#undef Bool
 #include <fileref.h>
 #include <tstring.h>
 #include <id3v1tag.h>
@@ -339,6 +339,7 @@ static void gm_strip_tags(TagLib::File * file,FXuint opts) {
 /******************************************************************************/
 
 GMFileTag::GMFileTag() :
+    fileref(nullptr),
     file(nullptr),
     tag(nullptr),
     mp4(nullptr),
@@ -349,20 +350,35 @@ GMFileTag::GMFileTag() :
   }
 
 GMFileTag::~GMFileTag() {
+#if TAGLIB_VERSION >= TAGVERSION(2,0,0)
+  if (fileref) delete fileref;
+#else
   if (file) delete file;
+#endif
   }
 
 
 FXbool GMFileTag::open(const FXString & filename,FXuint opts) {
-
-  file = TagLib::FileRef::create(filename.text(),(opts&FILETAG_AUDIOPROPERTIES));
-  if (file==nullptr || !file->isValid() || file->tag()==nullptr) {
-    if (file) {
-      delete file;
-      file=nullptr;
+#if TAGLIB_VERSION >= TAGVERSION(2,0,0)
+    fileref = new TagLib::FileRef(filename.text(),(opts&FILETAG_AUDIOPROPERTIES));
+    file = fileref->file();
+    if (file==nullptr || !file->isValid() || file->tag()==nullptr) {
+      if (fileref) {
+        delete fileref;
+        fileref=nullptr;
+        }
+      return false;
       }
-    return false;
-    }
+#else
+    file = TagLib::FileRef::create(filename.text(),(opts&FILETAG_AUDIOPROPERTIES));
+    if (file==nullptr || !file->isValid() || file->tag()==nullptr) {
+      if (file) {
+        delete file;
+        file=nullptr;
+        }
+      return false;
+      }
+#endif
 
   TagLib::MPEG::File        * mpgfile   = nullptr;
   TagLib::Ogg::Vorbis::File * oggfile   = nullptr;
@@ -521,7 +537,11 @@ FXbool GMFileTag::ape_get_field(const FXchar * field,FXStringList & list)  const
   FXASSERT(field);
   FXASSERT(ape);
   if (ape->itemListMap().contains(field)) {
+#if TAGLIB_VERSION >= TAGVERSION(2,0,0)
+    const TagLib::StringList fieldlist = ape->itemListMap()[field].values();
+#else
     const TagLib::StringList fieldlist = ape->itemListMap()[field].toStringList();
+#endif
     list.no(fieldlist.size());
     FXint item=0;
     for(TagLib::StringList::ConstIterator it = fieldlist.begin(); it != fieldlist.end(); it++) {
@@ -635,16 +655,35 @@ FXbool  GMFileTag::id3v2_get_field(const FXchar * field,FXStringList & list) con
 void GMFileTag::mp4_update_field(const FXchar * field,const FXString & value) {
   FXASSERT(field);
   FXASSERT(mp4);
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+  if (!value.empty())
+    mp4->setItem(field,TagLib::StringList(TagLib::String(value.text(),TagLib::String::UTF8)));
+  else
+    mp4->removeItem(field);
+#else
   if (!value.empty())
     mp4->itemListMap().insert(field,TagLib::StringList(TagLib::String(value.text(),TagLib::String::UTF8)));
   else
     mp4->itemListMap().erase(field);
+#endif
   }
 
 
 void GMFileTag::mp4_update_field(const FXchar * field,const FXStringList & list) {
   FXASSERT(field);
   FXASSERT(mp4);
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+  if (list.no()==0) {
+    mp4->removeItem(field);
+    }
+  else {
+    TagLib::StringList values;
+    for (FXint i=0;i<list.no();i++) {
+      values.append(TagLib::String(list[i].text(),TagLib::String::UTF8));
+      }
+    mp4->setItem(field,values);
+    }
+#else
   if (list.no()==0) {
     mp4->itemListMap().erase(field);
     }
@@ -655,12 +694,24 @@ void GMFileTag::mp4_update_field(const FXchar * field,const FXStringList & list)
       }
     mp4->itemListMap().insert(field,values);
     }
+#endif
   }
 
 
 FXbool GMFileTag::mp4_get_field(const FXchar * field,FXString & value) const {
   FXASSERT(field);
   FXASSERT(mp4);
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+  if (mp4->contains(field)) {
+    value=mp4->item(field).toStringList().toString(", ").toCString(true);
+    value.trim();
+    return !value.empty();
+    }
+  else {
+    value.clear();
+    return false;
+    }
+#else
   if (mp4->itemListMap().contains(field)) {
     value=mp4->itemListMap()[field].toStringList().toString(", ").toCString(true);
     value.trim();
@@ -670,14 +721,20 @@ FXbool GMFileTag::mp4_get_field(const FXchar * field,FXString & value) const {
     value.clear();
     return false;
     }
+#endif
   }
 
 
 FXbool GMFileTag::mp4_get_field(const FXchar * field,FXStringList & list) const{
   FXASSERT(field);
   FXASSERT(mp4);
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+  if (mp4->contains(field)) {
+    const TagLib::StringList fieldlist = mp4->item(field).toStringList();
+#else
   if (mp4->itemListMap().contains(field)) {
     const TagLib::StringList fieldlist = mp4->itemListMap()[field].toStringList();
+#endif
     list.no(fieldlist.size());
     FXint item=0;
     for(TagLib::StringList::ConstIterator it = fieldlist.begin(); it != fieldlist.end(); it++) {
@@ -936,12 +993,21 @@ void GMFileTag::setDiscNumber(FXushort disc) {
     else
       id3v2_update_field("TPOS",FXString::null);
     }
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+  if (mp4) {
+    if (disc>0)
+      mp4->setItem("disk",TagLib::MP4::Item(disc,0));
+    else
+      mp4->removeItem("disk");
+    }
+#else
   if (mp4) {
     if (disc>0)
       mp4->itemListMap().insert("disk",TagLib::MP4::Item(disc,0));
     else
       mp4->itemListMap().erase("disk");
     }
+#endif
   }
 
 
@@ -959,9 +1025,15 @@ FXushort GMFileTag::getDiscNumber() const{
   else if (id3v2 && id3v2_get_field("TPOS",disc)) {
     return string_to_disc_number(disc);
     }
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+  else if (mp4 && mp4->contains("disk")) {
+    return FXMIN(mp4->item("disk").toIntPair().first,0xFFFF);
+    }
+#else
   else if (mp4 && mp4->itemListMap().contains("disk")) {
     return FXMIN(mp4->itemListMap()["disk"].toIntPair().first,0xFFFF);
     }
+#endif
   return 0;
   }
 
@@ -969,7 +1041,11 @@ FXint GMFileTag::getTime() const{
   FXASSERT(file);
   TagLib::AudioProperties * properties = file->audioProperties();
   if (properties)
+#if TAGLIB_VERSION >= TAGVERSION(2,0,0)
+    return properties->lengthInSeconds();
+#else
     return properties->length();
+#endif
   else
     return 0;
   }
@@ -1007,7 +1083,11 @@ FXint GMFileTag::getSampleSize() const{
   FXASSERT(file);
   TagLib::FLAC::File * flacfile = dynamic_cast<TagLib::FLAC::File*>(file);
   if (flacfile && flacfile->audioProperties()) {
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+    return flacfile->audioProperties()->bitsPerSample();
+#else
     return flacfile->audioProperties()->sampleWidth();
+#endif
     }
   else
     return 0;
@@ -1081,6 +1161,16 @@ GMCover * GMFileTag::getFrontCover() const {
 #endif
     }
   else if (mp4) { /// MP4
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+    if (mp4->contains("covr")) {
+      TagLib::MP4::CoverArtList coverlist = mp4->item("covr").toCoverArtList();
+      for(TagLib::MP4::CoverArtList::Iterator it = coverlist.begin(); it != coverlist.end(); it++) {
+        if (it->data().size())
+          return new GMCover(it->data().data(),it->data().size());
+        }
+      }
+    }
+#else
     if (mp4->itemListMap().contains("covr")) {
       TagLib::MP4::CoverArtList coverlist = mp4->itemListMap()["covr"].toCoverArtList();
       for(TagLib::MP4::CoverArtList::Iterator it = coverlist.begin(); it != coverlist.end(); it++) {
@@ -1089,6 +1179,7 @@ GMCover * GMFileTag::getFrontCover() const {
         }
       }
     }
+#endif
   return nullptr;
   }
 
@@ -1134,6 +1225,15 @@ FXint GMFileTag::getCovers(GMCoverList & covers) const {
       }
     }
   else if (mp4) {
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+    if (mp4->contains("covr")) {
+      TagLib::MP4::CoverArtList coverlist = mp4->item("covr").toCoverArtList();
+      for(TagLib::MP4::CoverArtList::Iterator it = coverlist.begin(); it != coverlist.end(); it++) {
+        if (it->data().size())
+          covers.append(new GMCover(it->data().data(),it->data().size(),0));
+        }
+      }
+#else
     if (mp4->itemListMap().contains("covr")) {
       TagLib::MP4::CoverArtList coverlist = mp4->itemListMap()["covr"].toCoverArtList();
       for(TagLib::MP4::CoverArtList::Iterator it = coverlist.begin(); it != coverlist.end(); it++) {
@@ -1141,6 +1241,7 @@ FXint GMFileTag::getCovers(GMCoverList & covers) const {
           covers.append(new GMCover(it->data().data(),it->data().size(),0));
         }
       }
+#endif
     }
   return covers.no();
   }
@@ -1191,7 +1292,7 @@ void GMFileTag::replaceCover(GMCover*cover,FXuint mode){
       }
     else if (mp4) {
       // mp4 has no type information so we erase all
-      mp4->itemListMap().erase("covr");
+      clearCovers();
       }
     }
   else { // COVER_REPLACE_ALL
@@ -1216,7 +1317,11 @@ void GMFileTag::clearCovers() {
 #endif
     }
   else if (mp4) {
-    mp4->itemListMap().erase("covr");
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+      mp4->removeItem("covr");
+#else
+      mp4->itemListMap().erase("covr");
+#endif
     }
   }
 
@@ -1303,6 +1408,18 @@ void GMFileTag::appendCover(GMCover* cover){
       case FILETYPE_GIF: format = TagLib::MP4::CoverArt::GIF; break;
       default: return; break;
       }
+#if TAGLIB_VERSION >= TAGVERSION(1,12,0)
+    if (!mp4->contains("covr")) {
+      TagLib::MP4::CoverArtList list;
+      list.append(TagLib::MP4::CoverArt(format,TagLib::ByteVector((const FXchar*)cover->data,cover->size)));
+      mp4->setItem("covr",list);
+      }
+    else {
+      TagLib::MP4::CoverArtList list = mp4->item("covr").toCoverArtList();
+      list.append(TagLib::MP4::CoverArt(format,TagLib::ByteVector((const FXchar*)cover->data,cover->size)));
+      mp4->setItem("covr",list);
+      }
+#else
     if (!mp4->itemListMap().contains("covr")) {
       TagLib::MP4::CoverArtList list;
       list.append(TagLib::MP4::CoverArt(format,TagLib::ByteVector((const FXchar*)cover->data,cover->size)));
@@ -1313,6 +1430,7 @@ void GMFileTag::appendCover(GMCover* cover){
       list.append(TagLib::MP4::CoverArt(format,TagLib::ByteVector((const FXchar*)cover->data,cover->size)));
       mp4->itemListMap().insert("covr",list);
       }
+#endif
     }
 }
 
diff --git a/src/GMTag.h b/src/GMTag.h
index 26b76f2..1c5fd77 100644
--- a/src/GMTag.h
+++ b/src/GMTag.h
@@ -21,6 +21,7 @@
 
 
 namespace TagLib {
+  class FileRef;
   class File;
   class Tag;
   namespace MP4 {
@@ -54,6 +55,7 @@ typedef FXArray<GMCover*> GMCoverList;
 
 class GMFileTag {
 protected:
+  TagLib::FileRef           * fileref;
   TagLib::File              * file;
   TagLib::Tag               * tag;
   TagLib::MP4::Tag          * mp4;
