Git commit 59867f7b1a5214664d256db5d7b91972b63794dd by Thomas Eschenbacher, on 
behalf of Thomas Eschenbacher.
Committed on 29/08/2026 at 16:53.
Pushed by eschenbacher into branch 'master'.

finished migration from id3lib to taglib

M  +1    -42   .flatpak-manifest.json
D  +0    -14   .flatpak-patches/00-add-libz-to-compilation.patch
D  +0    -12   .flatpak-patches/05-create-m4-directory.patch
D  +0    -22   .flatpak-patches/10-fix-compilation-with-cpp-headers.patch
D  +0    -45   .flatpak-patches/15-fix-headers-of-main-functions.patch
D  +0    -38   .flatpak-patches/30-fix-utf16.patch
D  +0    -24   .flatpak-patches/31-fix-utf16-stringlists.patch
D  +0    -54   .flatpak-patches/40-deal-with-mkstemp.patch
D  +0    -21   .flatpak-patches/50-remove-outdated-check.patch
D  +0    -58   .flatpak-patches/60-add-c-wrapper-functions.patch
D  +0    -50   .flatpak-patches/60-fix_make_check.patch
D  +0    -12   .flatpak-patches/60-id3lib-missing-nullpointer-check.patch
D  +0    -19   .flatpak-patches/61-fix_vbr_stack_smash.patch
D  +0    -32   .flatpak-patches/62-remove-remote-icons.patch
D  +0    -4    .flatpak-patches/README
D  +0    -55   .flatpak-patches/copyright
M  +3    -1    CHANGES
M  +2    -8    LICENSES
M  +10   -8    TODO
M  +0    -3    doc/devel.docbook
M  +0    -5    kwave/main.cpp
M  +1    -23   plugins/codec_mp3/CMakeLists.txt
D  +0    -321  plugins/codec_mp3/ID3_PropertyMap.cpp
D  +0    -130  plugins/codec_mp3/ID3_PropertyMap.h
D  +0    -103  plugins/codec_mp3/ID3_QIODeviceReader.cpp
D  +0    -82   plugins/codec_mp3/ID3_QIODeviceReader.h
D  +0    -100  plugins/codec_mp3/ID3_QIODeviceWriter.cpp
D  +0    -93   plugins/codec_mp3/ID3_QIODeviceWriter.h
M  +232  -195  plugins/codec_mp3/MP3Encoder.cpp
M  +6    -4    plugins/codec_mp3/MP3Encoder.h

https://invent.kde.org/multimedia/kwave/-/commit/59867f7b1a5214664d256db5d7b91972b63794dd

diff --git a/.flatpak-manifest.json b/.flatpak-manifest.json
index 5bca9d2c..37b16016 100644
--- a/.flatpak-manifest.json
+++ b/.flatpak-manifest.json
@@ -40,47 +40,6 @@
                 "/bin"
             ]
         },
-        {
-            "name": "id3lib",
-            "buildsystem": "autotools",
-            "config-opts": [
-                "--disable-static"
-            ],
-            "sources": [
-                {
-                    "type": "archive",
-                    "url": 
"http://downloads.sourceforge.net/id3lib/id3lib-3.8.3.tar.gz";,
-                    "sha256": 
"2749cc3c0cd7280b299518b1ddf5a5bcfe2d1100614519b68702230e26c7d079"
-                },
-                {
-                    "type": "patch",
-                    "paths": [
-                        ".flatpak-patches/00-add-libz-to-compilation.patch",
-                        ".flatpak-patches/05-create-m4-directory.patch",
-                        
".flatpak-patches/10-fix-compilation-with-cpp-headers.patch",
-                        
".flatpak-patches/15-fix-headers-of-main-functions.patch",
-                        ".flatpak-patches/30-fix-utf16.patch",
-                        ".flatpak-patches/31-fix-utf16-stringlists.patch",
-                        ".flatpak-patches/40-deal-with-mkstemp.patch",
-                        ".flatpak-patches/50-remove-outdated-check.patch",
-                        ".flatpak-patches/60-add-c-wrapper-functions.patch",
-                        ".flatpak-patches/60-fix_make_check.patch",
-                        
".flatpak-patches/60-id3lib-missing-nullpointer-check.patch",
-                        ".flatpak-patches/61-fix_vbr_stack_smash.patch",
-                        ".flatpak-patches/62-remove-remote-icons.patch"
-                    ]
-                },
-                {
-                    "type": "shell",
-                    "commands": [
-                        "cp -p /usr/share/automake-*/config.{sub,guess} ."
-                    ]
-                }
-            ],
-            "cleanup": [
-                "/bin"
-            ]
-        },
         {
             "name": "libmad",
             "buildsystem": "cmake-ninja",
@@ -103,7 +62,7 @@
                 {
                     "type": "archive",
                     "url": 
"https://taglib.github.io/releases/taglib-2.0.2.tar.gz";,
-                    "sha256": 
"43242202ed726618764010375f4d80a1a0f82d259c63c32e541459a0d24ee312"
+                    "sha256": 
"0de288d7fe34ba133199fd8512f19cc1100196826eafcb67a33b224ec3a59737"
                 }
             ]
         },
diff --git a/.flatpak-patches/00-add-libz-to-compilation.patch 
b/.flatpak-patches/00-add-libz-to-compilation.patch
deleted file mode 100644
index e9378773..00000000
--- a/.flatpak-patches/00-add-libz-to-compilation.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-This patch was first introduced in version 3.8.3-3
-
-It fixes http://bugs.debian.org/208672
---- a/src/Makefile.am
-+++ b/src/Makefile.am
-@@ -74,6 +74,8 @@
- 
- if ID3_NEEDZLIB
- LDADD        = $(top_builddir)/zlib/src/libz.la
-+else
-+libid3_la_LIBADD  = -lz
- endif
- 
- libid3_la_LDFLAGS = \
diff --git a/.flatpak-patches/05-create-m4-directory.patch 
b/.flatpak-patches/05-create-m4-directory.patch
deleted file mode 100644
index d8111205..00000000
--- a/.flatpak-patches/05-create-m4-directory.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-Create a local m4 subdirectory
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -12,6 +12,8 @@
- # require automake 1.5
- AUTOMAKE_OPTIONS = 1.5
- 
-+ACLOCAL_AMFLAGS = -I m4
-+
- EXTRA_DIST =                    \
-         HISTORY                 \
-         config.h.win32          \
diff --git a/.flatpak-patches/10-fix-compilation-with-cpp-headers.patch 
b/.flatpak-patches/10-fix-compilation-with-cpp-headers.patch
deleted file mode 100644
index a9b45ab0..00000000
--- a/.flatpak-patches/10-fix-compilation-with-cpp-headers.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-This patch imports the proper C++ headers
---- a/include/id3/id3lib_strings.h
-+++ b/include/id3/id3lib_strings.h
-@@ -30,6 +30,7 @@
- #define _ID3LIB_STRINGS_H_
- 
- #include <string>
-+#include <cstring>
- 
- #if (defined(__GNUC__) && (__GNUC__ >= 3) || (defined(_MSC_VER) && _MSC_VER > 
1000))
- namespace std
---- a/include/id3/writers.h
-+++ b/include/id3/writers.h
-@@ -30,7 +30,7 @@
- 
- #include "id3/writer.h"
- #include "id3/id3lib_streams.h"
--//#include <string.h>
-+#include <cstring>
- 
- class ID3_CPP_EXPORT ID3_OStreamWriter : public ID3_Writer
- {
diff --git a/.flatpak-patches/15-fix-headers-of-main-functions.patch 
b/.flatpak-patches/15-fix-headers-of-main-functions.patch
deleted file mode 100644
index 48e01d14..00000000
--- a/.flatpak-patches/15-fix-headers-of-main-functions.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-This patch fixes some function headers in demo code used during 'make check'
---- a/examples/demo_info.cpp
-+++ b/examples/demo_info.cpp
-@@ -309,7 +309,7 @@
- 
- #define DEBUG
- 
--int main( unsigned int argc, char * const argv[])
-+int main(int argc, char * const argv[])
- {
-   ID3D_INIT_DOUT();
- 
---- a/examples/demo_convert.cpp
-+++ b/examples/demo_convert.cpp
-@@ -84,7 +84,7 @@
-   }
- }
- 
--int main( unsigned int argc, char * const argv[])
-+int main(int argc, char * const argv[])
- {
-   flags_t ulFlag = ID3TT_ALL;
-   gengetopt_args_info args;
---- a/examples/demo_copy.cpp
-+++ b/examples/demo_copy.cpp
-@@ -81,7 +81,7 @@
-   }
- }
- 
--int main( unsigned int argc, char * const argv[])
-+int main(int argc, char * const argv[])
- {
-   int ulFlag = ID3TT_ID3;
-   ID3D_INIT_DOUT();
---- a/examples/demo_tag.cpp
-+++ b/examples/demo_tag.cpp
-@@ -46,7 +46,7 @@
-     os << "v2";
- }
- 
--int main( unsigned int argc, char * const argv[])
-+int main(int argc, char * const argv[])
- {
-   int ulFlag = ID3TT_ID3;
-   ID3D_INIT_DOUT();
diff --git a/.flatpak-patches/30-fix-utf16.patch 
b/.flatpak-patches/30-fix-utf16.patch
deleted file mode 100644
index 3d3f50fe..00000000
--- a/.flatpak-patches/30-fix-utf16.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-Patch from 'Spoon' to fix issues with writing certain unicode characters
---- a/ChangeLog
-+++ b/ChangeLog
-@@ -1,3 +1,8 @@
-+2006-02-17  Jerome Couderc
-+
-+    * Patch from Spoon to fix UTF-16 writing bug
-+      
http://sourceforge.net/tracker/index.php?func=detail&aid=1016290&group_id=979&atid=300979
-+
- 2003-03-02 Sunday 17:38   Thijmen Klok <[email protected]>
- 
-       * THANKS (1.20): added more people 
---- a/src/io_helpers.cpp
-+++ b/src/io_helpers.cpp
-@@ -363,11 +363,22 @@
-     // Write the BOM: 0xFEFF
-     unicode_t BOM = 0xFEFF;
-     writer.writeChars((const unsigned char*) &BOM, 2);
-+    // Patch from Spoon : 2004-08-25 14:17
-+    //   
http://sourceforge.net/tracker/index.php?func=detail&aid=1016290&group_id=979&atid=300979
-+    // Wrong code
-+    //for (size_t i = 0; i < size; i += 2)
-+    //{
-+    //  unicode_t ch = (data[i] << 8) | data[i+1];
-+    //  writer.writeChars((const unsigned char*) &ch, 2);
-+    //}
-+    // Right code
-+    unsigned char *pdata = (unsigned char *) data.c_str();
-     for (size_t i = 0; i < size; i += 2)
-     {
--      unicode_t ch = (data[i] << 8) | data[i+1];
-+      unicode_t ch = (pdata[i] << 8) | pdata[i+1];
-       writer.writeChars((const unsigned char*) &ch, 2);
-     }
-+    // End patch
-   }
-   return writer.getCur() - beg;
- }
diff --git a/.flatpak-patches/31-fix-utf16-stringlists.patch 
b/.flatpak-patches/31-fix-utf16-stringlists.patch
deleted file mode 100644
index 35822387..00000000
--- a/.flatpak-patches/31-fix-utf16-stringlists.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-This patch fixes tag corruption after pipe characters.
-
-Author: Urs Fleisch <[email protected]>
-Fixes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=680915
---- a/src/io_helpers.cpp
-+++ b/src/io_helpers.cpp
-@@ -373,10 +373,17 @@
-     //}
-     // Right code
-     unsigned char *pdata = (unsigned char *) data.c_str();
-+    unicode_t lastCh = BOM;
-     for (size_t i = 0; i < size; i += 2)
-     {
-       unicode_t ch = (pdata[i] << 8) | pdata[i+1];
-+      if (lastCh == 0 && ch != BOM)
-+      {
-+        // Last character was NULL, so start next string with BOM.
-+        writer.writeChars((const unsigned char*) &BOM, 2);
-+      }
-       writer.writeChars((const unsigned char*) &ch, 2);
-+      lastCh = ch;
-     }
-     // End patch
-   }
diff --git a/.flatpak-patches/40-deal-with-mkstemp.patch 
b/.flatpak-patches/40-deal-with-mkstemp.patch
deleted file mode 100644
index 36c84179..00000000
--- a/.flatpak-patches/40-deal-with-mkstemp.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-This patch fixes an issues where temporary files were created in an insecure
-way.
-
-It was first intruduced in version 3.8.3-7 and fixes
-http://bugs.debian.org/438540
---- a/src/tag_file.cpp
-+++ b/src/tag_file.cpp
-@@ -242,8 +242,8 @@
-     strcpy(sTempFile, filename.c_str());
-     strcat(sTempFile, sTmpSuffix.c_str());
- 
--#if ((defined(__GNUC__) && __GNUC__ >= 3  ) || !defined(HAVE_MKSTEMP))
--    // This section is for Windows folk && gcc 3.x folk
-+#if !defined(HAVE_MKSTEMP)
-+    // This section is for Windows folk
-     fstream tmpOut;
-     createFile(sTempFile, tmpOut);
- 
-@@ -257,7 +257,7 @@
-       tmpOut.write((char *)tmpBuffer, nBytes);
-     }
- 
--#else //((defined(__GNUC__) && __GNUC__ >= 3  ) || !defined(HAVE_MKSTEMP))
-+#else //!defined(HAVE_MKSTEMP)
- 
-     // else we gotta make a temp file, copy the tag into it, copy the
-     // rest of the old file after the tag, delete the old file, rename
-@@ -270,7 +270,7 @@
-       //ID3_THROW_DESC(ID3E_NoFile, "couldn't open temp file");
-     }
- 
--    ofstream tmpOut(fd);
-+    ofstream tmpOut(sTempFile);
-     if (!tmpOut)
-     {
-       tmpOut.close();
-@@ -285,14 +285,14 @@
-     uchar tmpBuffer[BUFSIZ];
-     while (file)
-     {
--      file.read(tmpBuffer, BUFSIZ);
-+      file.read((char *)tmpBuffer, BUFSIZ);
-       size_t nBytes = file.gcount();
--      tmpOut.write(tmpBuffer, nBytes);
-+      tmpOut.write((char *)tmpBuffer, nBytes);
-     }
- 
-     close(fd); //closes the file
- 
--#endif ////((defined(__GNUC__) && __GNUC__ >= 3  ) || !defined(HAVE_MKSTEMP))
-+#endif ////!defined(HAVE_MKSTEMP)
- 
-     tmpOut.close();
-     file.close();
diff --git a/.flatpak-patches/50-remove-outdated-check.patch 
b/.flatpak-patches/50-remove-outdated-check.patch
deleted file mode 100644
index b1c33d78..00000000
--- a/.flatpak-patches/50-remove-outdated-check.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-We don't actually need iomanip.h
---- a/configure.in
-+++ b/configure.in
-@@ -227,7 +227,6 @@
- )
- AC_CHECK_HEADERS(               \
-   string                        \
--  iomanip.h                     \
-   ,,AC_MSG_ERROR([Missing a vital header file for id3lib])
- )
- 
---- a/configure
-+++ b/configure
-@@ -10296,7 +10296,6 @@
- 
- for ac_header in \
-   string                        \
--  iomanip.h                     \
- 
- do
- as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
diff --git a/.flatpak-patches/60-add-c-wrapper-functions.patch 
b/.flatpak-patches/60-add-c-wrapper-functions.patch
deleted file mode 100644
index d72e81c0..00000000
--- a/.flatpak-patches/60-add-c-wrapper-functions.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-This patch adds C wrapper functions for field encoding.
-
-It was first introduced in version 3.8.3-8 and fixes
-http://bugs.debian.org/281292
---- a/include/id3.h
-+++ b/include/id3.h
-@@ -104,6 +104,9 @@
-   ID3_C_EXPORT void                 CCONV ID3Field_GetBINARY          (const 
ID3Field *field, uchar *buffer, size_t buffLength);
-   ID3_C_EXPORT void                 CCONV ID3Field_FromFile           
(ID3Field *field, const char *fileName);
-   ID3_C_EXPORT void                 CCONV ID3Field_ToFile             (const 
ID3Field *field, const char *fileName);
-+  ID3_C_EXPORT bool                 CCONV ID3Field_SetEncoding        
(ID3Field *field, ID3_TextEnc enc);
-+  ID3_C_EXPORT ID3_TextEnc          CCONV ID3Field_GetEncoding        (const 
ID3Field *field);
-+  ID3_C_EXPORT bool                 CCONV ID3Field_IsEncodable        (const 
ID3Field *field);
- 
-   /* field-info wrappers */
-   ID3_C_EXPORT char*                CCONV ID3FrameInfo_ShortName     
(ID3_FrameID frameid);
---- a/src/c_wrapper.cpp
-+++ b/src/c_wrapper.cpp
-@@ -681,6 +681,39 @@
-     }
-   }
- 
-+  ID3_C_EXPORT bool CCONV
-+  ID3Field_SetEncoding(ID3Field *field, ID3_TextEnc enc)
-+  {
-+    bool changed = false;
-+    if (field)
-+    {
-+      ID3_CATCH(changed = reinterpret_cast<ID3_Field 
*>(field)->SetEncoding(enc));
-+    }
-+    return changed;
-+  }
-+
-+  ID3_C_EXPORT ID3_TextEnc CCONV
-+  ID3Field_GetEncoding(const ID3Field *field)
-+  {
-+    ID3_TextEnc enc = ID3TE_NONE;
-+    if (field)
-+    {
-+      ID3_CATCH(enc = reinterpret_cast<const ID3_Field 
*>(field)->GetEncoding());
-+    }
-+    return enc;
-+  }
-+
-+  ID3_C_EXPORT bool CCONV
-+  ID3Field_IsEncodable(const ID3Field *field)
-+  {
-+    bool isEncodable = false;
-+    if (field)
-+    {
-+      ID3_CATCH(isEncodable = reinterpret_cast<const ID3_Field 
*>(field)->IsEncodable());
-+    }
-+    return isEncodable;
-+  }
-+
- #ifdef __cplusplus
- }
- #endif /* __cplusplus */
diff --git a/.flatpak-patches/60-fix_make_check.patch 
b/.flatpak-patches/60-fix_make_check.patch
deleted file mode 100644
index e2bb1b05..00000000
--- a/.flatpak-patches/60-fix_make_check.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-This patch fixes some function headers and imports in order for 'make check'
-to work.
-
-It was first introduced in version 3.8.3-9
-diff -Naur id3lib-3.8.3.orig/examples/findeng.cpp 
id3lib-3.8.3/examples/findeng.cpp
---- id3lib-3.8.3.orig/examples/findeng.cpp     2003-03-02 01:23:00.000000000 
+0100
-+++ id3lib-3.8.3/examples/findeng.cpp  2009-12-10 00:58:12.173795997 +0100
-@@ -9,7 +9,7 @@
- using std::cout;
- using std::endl;
- 
--int main(unsigned argc, char* argv[])
-+int main(int argc, char* argv[])
- {
-   ID3D_INIT_DOUT();
-   ID3D_INIT_WARNING();
-diff -Naur id3lib-3.8.3.orig/examples/findstr.cpp 
id3lib-3.8.3/examples/findstr.cpp
---- id3lib-3.8.3.orig/examples/findstr.cpp     2003-03-02 01:23:00.000000000 
+0100
-+++ id3lib-3.8.3/examples/findstr.cpp  2009-12-10 00:57:48.036819825 +0100
-@@ -9,7 +9,7 @@
- using std::cout;
- using std::endl;
- 
--int main(unsigned argc, char* argv[])
-+int main(int argc, char* argv[])
- {
-   ID3D_INIT_DOUT();
-   ID3D_INIT_WARNING();
-diff -Naur id3lib-3.8.3.orig/examples/test_io.cpp 
id3lib-3.8.3/examples/test_io.cpp
---- id3lib-3.8.3.orig/examples/test_io.cpp     2003-03-02 01:23:00.000000000 
+0100
-+++ id3lib-3.8.3/examples/test_io.cpp  2009-12-10 00:57:03.612111640 +0100
-@@ -11,6 +11,9 @@
- #include <id3/io_strings.h>
- #include <id3/utils.h>
- 
-+using std::cin;
-+using std::hex;
-+using std::dec;
- using std::cout;
- using std::endl;
- using std::cerr;
-@@ -18,7 +21,7 @@
- using namespace dami;
- 
- int
--main(size_t argc, const char** argv)
-+main(int argc, const char** argv)
- {
-   ID3D_INIT_DOUT();
-   ID3D_INIT_WARNING();
diff --git a/.flatpak-patches/60-id3lib-missing-nullpointer-check.patch 
b/.flatpak-patches/60-id3lib-missing-nullpointer-check.patch
deleted file mode 100644
index d4ca5d29..00000000
--- a/.flatpak-patches/60-id3lib-missing-nullpointer-check.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-This patch adds a check for a null pointer
---- a/src/header_tag.cpp
-+++ b/src/header_tag.cpp
-@@ -54,7 +54,7 @@
- {
-   size_t bytesUsed = ID3_TagHeader::SIZE;
- 
--  if (_info->is_extended)
-+  if (_info && _info->is_extended)
-   {
-     bytesUsed += _info->extended_bytes;
-   }
diff --git a/.flatpak-patches/61-fix_vbr_stack_smash.patch 
b/.flatpak-patches/61-fix_vbr_stack_smash.patch
deleted file mode 100644
index 9bf33e97..00000000
--- a/.flatpak-patches/61-fix_vbr_stack_smash.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-Description: Fix crashes when reading VBR MP3 file.
-Bug-Ubuntu: https://launchpad.net/bugs/444466
-Origin: upstream, 
http://sourceforge.net/tracker/?func=detail&aid=937707&group_id=979&atid=300979
-Forwarded: yes
-Author: Urs Fleisch
-
-Index: id3lib3.8.3-3.8.3/src/mp3_parse.cpp
-===================================================================
---- id3lib3.8.3-3.8.3.orig/src/mp3_parse.cpp   2009-10-06 23:12:10.381250132 
+0200
-+++ id3lib3.8.3-3.8.3/src/mp3_parse.cpp        2009-10-06 23:14:09.545252591 
+0200
-@@ -465,7 +465,7 @@
-   // from http://www.xingtech.com/developer/mp3/
- 
-   const size_t VBR_HEADER_MIN_SIZE = 8;     // "xing" + flags are fixed
--  const size_t VBR_HEADER_MAX_SIZE = 116;   // frames, bytes, toc and scale 
are optional
-+  const size_t VBR_HEADER_MAX_SIZE = 120;   // frames, bytes, toc and scale 
are optional
- 
-   if (mp3size >= vbr_header_offest + VBR_HEADER_MIN_SIZE) 
-   {
diff --git a/.flatpak-patches/62-remove-remote-icons.patch 
b/.flatpak-patches/62-remove-remote-icons.patch
deleted file mode 100644
index 6d929953..00000000
--- a/.flatpak-patches/62-remove-remote-icons.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-This patch removes two icons from the documentation which would be loaded from
-remote servers, thereby exposing the reader's IP address to potential tracking
-(lintian keywords privacy-breach-logo and privacy-breach-w3c-valid-html).
-
-Author: Stefan Ott <[email protected]>
---- a/doc/index.html
-+++ b/doc/index.html
-@@ -427,24 +427,5 @@
-         </td>
-       </tr>
-     </table>
--    
--    <br><br>
--    
--    <table align="center" width="80%" border="0">
--      <tr>
--        <td align="left">
--          <a href="http://sourceforge.net";>
--            <IMG 
src="http://sourceforge.net/sflogo.php?group_id=979&amp;type=1"; width="88" 
height="31" border="0" alt="SourceForge.net"></A>
--        </td>
--        <td align="right">
--
--          <a href="http://validator.w3.org/check/referer";>
--            <img border=0
--              src="http://validator.w3.org/images/vh401";
--              alt="Valid HTML 4.01!" height=31 width=88></a>
--        </td>
--      </tr>
--    </table>
--    <br>
-   </body>
- </html>
diff --git a/.flatpak-patches/README b/.flatpak-patches/README
deleted file mode 100644
index ee039d27..00000000
--- a/.flatpak-patches/README
+++ /dev/null
@@ -1,4 +0,0 @@
-These patches are only used when building a flatpak. id3lib is unmaintained, 
so these patches are needed to build it.
-
-id3lib patches downloaded from 
https://sources.debian.org/src/id3lib3.8.3/3.8.3-18/debian/patches/
-copyright file downloaded from 
https://sources.debian.org/src/id3lib3.8.3/3.8.3-18/debian/copyright/
diff --git a/.flatpak-patches/copyright b/.flatpak-patches/copyright
deleted file mode 100644
index f2c72991..00000000
--- a/.flatpak-patches/copyright
+++ /dev/null
@@ -1,55 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: id3lib
-Source: http://id3lib.sourceforge.net/
-
-Files: *
-Copyright: Copyright 1999, 2000, Scott Thomas Haug <[email protected]>
-License: LGPL-2+
- id3lib: a C++ library for creating and manipulating id3v1/v2 tags
- Copyright 1999, 2000  Scott Thomas Haug
- .
- This library is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published by
- the Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
- .
- This library is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
- License for more details.
- .
- You should have received a copy of the GNU Library General Public License
- along with this library; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- .
- The id3lib authors encourage improvements and optimisations to be sent to
- the id3lib coordinator.  Please see the README file for details on where to
- send such submissions.  See the AUTHORS file for a list of people who have
- contributed to id3lib.  See the ChangeLog file for a list of changes to
- id3lib.  These files are distributed with id3lib at
- http://download.sourceforge.net/id3lib/
- .
- On Debian systems, the full text of the GNU Library General Public
- License version 2 can be found in the file
- `/usr/share/common-licenses/LGPL-2'.
-
-Files: debian/*
-Copyright: 2009-2014, Stefan Ott <[email protected]>
-License: GPL-2+
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- .
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
- .
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- .
- On Debian systems, the full text of the GNU Library General Public
- License version 2 can be found in the file
- `/usr/share/common-licenses/GPL-2'.
diff --git a/CHANGES b/CHANGES
index 979c922e..f1d67dee 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,7 +6,9 @@
    - implemented encoder, adding support for saving in many legacy formats,
      including meta data and cue lists (as far as supported by libaudiofile)
  * codec_flac: parallelized decoding + added check for > 8 channels
- * codec_mp3: workaround for broken MBS conversion in ID3LIB
+ * codec_mp3:
+   - workaround for broken MBS conversion in ID3LIB
+   - migrated from id3lib to taglib
  * codec_mp3: do no longer explicitly link against libstdc++ and libz
  * codec_ogg: parallelized decoding of ogg/opus and ogg/vorbis
  * codec_ogg: support for up to 255 channels for ogg/opus and ogg/vorbis
diff --git a/LICENSES b/LICENSES
index a02e05c2..6c47ca49 100644
--- a/LICENSES
+++ b/LICENSES
@@ -43,8 +43,8 @@ DIRECTLY USED EXTERNAL LIBRARIES
         * KDE frameworks                LGPL2
         * FFTW-3                        GPL2+
         * audiofile                     LGPL2+ / GPL2+
-        * id3lib                        LGPL2.1
-        * mad                           GPL2+ <= possible patent issue !!!
+        * taglib                        LGPL2.1/MPL1.1
+        * mad                           GPL2+
         * ogg                           ~BSD style
         * flac                          Xiph.Org's BSD-like + GPL2 + LGPL2
         * alsa-lib                      LGPL2.1
@@ -539,12 +539,6 @@ COMPLETE LIST OF FILES AND THEIR LICENSE
         plugins/codec_flac/kwaveplugin_codec_flac.json.in    (UNKNOWN)
 
         plugins/codec_mp3/CMakeLists.txt                BSD (3 clause)
-        plugins/codec_mp3/ID3_PropertyMap.cpp           GPL2+
-        plugins/codec_mp3/ID3_PropertyMap.h             GPL2+
-        plugins/codec_mp3/ID3_QIODeviceReader.cpp       GPL2+
-        plugins/codec_mp3/ID3_QIODeviceReader.h         GPL2+
-        plugins/codec_mp3/ID3_QIODeviceWriter.cpp       GPL2+
-        plugins/codec_mp3/ID3_QIODeviceWriter.h         GPL2+
         plugins/codec_mp3/kwaveplugin_codec_mp3.json.in      (UNKNOWN)
         plugins/codec_mp3/MP3CodecPlugin.cpp            GPL2+
         plugins/codec_mp3/MP3CodecPlugin.h              GPL2+
diff --git a/TODO b/TODO
index 2402dba4..486938aa 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,13 @@
 
+o migrate MP3 import from libmad to libmpg123
+
+o use libmp3lame natively for MP3 export
+
+o migrate from libaudiofile to libsndfile
+
+o FileInfo dialog: consequently disable properties which are not
+  supported by encoder
+
 o collapse/expand of track views
 
 o add views with meta data
@@ -25,7 +34,7 @@ o FLAC in Ogg container
 
 o SPEEX in Ogg container
 
-o ALAC support (via libaudiofile)
+o ALAC support
 
 o codec_wav: disable workaround for fact chunk == 0 as soon as a newer
   version of libaudiofile is available which can handle this
@@ -143,13 +152,6 @@ o user selectable color scheme
 
 o re-evaluate use of taglib as alternative to id3lib
 
-o port from id3lib to taglib
-  => rejected, currently no alternative available
-  => taglib currently works only on files, unsuitable API
-     + inaccurate file length detection (units of 1 sec)
-  => libid3tag is nearly as old, undocumented and would
-      produce a lot of work
-
 o switch to use float as sample_t (requires much work...)
   -> version 0.9.x
 
diff --git a/doc/devel.docbook b/doc/devel.docbook
index cf2ad9b1..23c2ecad 100644
--- a/doc/devel.docbook
+++ b/doc/devel.docbook
@@ -158,9 +158,6 @@
            <listitem><para>
                PulseAudio 4.0 or higher (for record/playback)
            </para></listitem>
-           <listitem><para>
-               id3lib-3.8.1 or higher (for ID3 tags)
-           </para></listitem>
            <listitem><para>
                mad-0.15 or higher (optionally for MP3 import/export)
            </para></listitem>
diff --git a/kwave/main.cpp b/kwave/main.cpp
index 88fa1bc0..c39a1469 100644
--- a/kwave/main.cpp
+++ b/kwave/main.cpp
@@ -116,11 +116,6 @@ static void addDataStrings(KAboutData &aboutdata)
         i18n("Author of the 'mad' MP3 decoder library"),
         _("[email protected]"),
         i18n("http://www.mars.org/home/rob/proj/mpeg";));
-    aboutdata.addCredit(
-        i18n("T.H.F. Klok and Cedric Tefft"),
-        i18n("Maintainers of the 'id3lib' library"),
-        QString(),
-        i18n("http://www.id3lib.org/";));
     aboutdata.addCredit(
         i18n("Michael Pruett"),
         i18n("Author of the 'audiofile' library"),
diff --git a/plugins/codec_mp3/CMakeLists.txt b/plugins/codec_mp3/CMakeLists.txt
index 33cdbd00..ca229eba 100644
--- a/plugins/codec_mp3/CMakeLists.txt
+++ b/plugins/codec_mp3/CMakeLists.txt
@@ -30,9 +30,6 @@ IF (WITH_MP3)
     PKG_CHECK_MODULES(MADLIB REQUIRED mad>=0.15.0)
     PKG_CHECK_MODULES(TAGLIB REQUIRED taglib>=2.0)
 
-    ### TODO legacy ###
-    find_library(ID3LIB NAMES id3 REQUIRED)
-
     SET(HAVE_MP3  ON CACHE BOOL "enable MP3 codec")
 
     INCLUDE_DIRECTORIES(
@@ -46,9 +43,6 @@ IF (WITH_MP3)
     )
 
     SET(plugin_codec_mp3_LIB_SRCS
-        ID3_PropertyMap.cpp
-        ID3_QIODeviceReader.cpp ### TODO legacy ###
-        ID3_QIODeviceWriter.cpp ### TODO legacy ###
         MP3CodecPlugin.cpp
         MP3Decoder.cpp
         MP3Encoder.cpp
@@ -56,9 +50,6 @@ IF (WITH_MP3)
         MP3EncoderSettings.cpp
         TagLib_PropertyMap.cpp
 
-        ID3_PropertyMap.h
-        ID3_QIODeviceReader.h ### TODO legacy ###
-        ID3_QIODeviceWriter.h ### TODO legacy ###
         MP3CodecPlugin.h
         MP3Decoder.h
         MP3Encoder.h
@@ -73,22 +64,9 @@ IF (WITH_MP3)
     )
 
     SET(plugin_codec_mp3_LIBS
-        ${MADLIB_LIBRARIES} ${ID3LIB} ${TAGLIB_LIBRARIES}
+        ${MADLIB_LIBRARIES} ${TAGLIB_LIBRARIES}
     )
 
-    ### TODO legacy ###
-    INCLUDE(CheckCXXCompilerFlag)
-    CHECK_CXX_COMPILER_FLAG("-Wno-non-virtual-dtor" HAVE_WNO_NON_VIRTUAL_DTOR)
-    IF (HAVE_WNO_NON_VIRTUAL_DTOR)
-        SET_SOURCE_FILES_PROPERTIES(
-            MP3Decoder.cpp
-            MP3Encoder.cpp
-            ID3_QIODeviceReader.cpp
-            ID3_QIODeviceWriter.cpp
-            PROPERTIES COMPILE_FLAGS "-Wno-non-virtual-dtor"
-        )
-    ENDIF (HAVE_WNO_NON_VIRTUAL_DTOR)
-
     KWAVE_PLUGIN(codec_mp3)
 
 ENDIF (WITH_MP3)
diff --git a/plugins/codec_mp3/ID3_PropertyMap.cpp 
b/plugins/codec_mp3/ID3_PropertyMap.cpp
deleted file mode 100644
index 28e34228..00000000
--- a/plugins/codec_mp3/ID3_PropertyMap.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/*************************************************************************
-    ID3_PropertyMap.cpp  -  map for translating properties to ID3 frame tags
-                             -------------------
-    begin                : Sat Jul 30 2012
-    copyright            : (C) 2012 by Thomas Eschenbacher
-    email                : [email protected]
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#include "config.h"
-
-#include <id3/field.h>
-
-#include "ID3_PropertyMap.h"
-
-//***************************************************************************
-Kwave::ID3_PropertyMap::ID3_PropertyMap()
-    :m_list()
-{
-    // NOTE #1: the first column is allowed to have multiple entries with the
-    //          same property, when encoding the first one is used, when
-    //          decoding, the other ones serve as alternatives
-    // NOTE #2: the ID3 tag names in the secondt column must be *unique* !
-
-    // Album/Movie/Show title
-    insert(Kwave::INF_ALBUM,         ID3FID_ALBUM,
-           ENC_TEXT);
-    // Original album/movie/show title
-    insert(Kwave::INF_ALBUM,         ID3FID_ORIGALBUM,
-           ENC_TEXT);
-    // Subtitle/Description refinement
-    insert(Kwave::INF_ANNOTATION,    ID3FID_SUBTITLE,
-           ENC_TEXT);
-    // User defined text information
-    insert(Kwave::INF_ANNOTATION,    ID3FID_USERTEXT,
-           ENC_TEXT);
-    //     Kwave::INF_ARCHIVAL
-    // Original artist(s)/performer(s)
-    insert(Kwave::INF_AUTHOR,        ID3FID_ORIGARTIST,
-           ENC_TEXT_SLASH);
-    // Involved people list
-    insert(Kwave::INF_AUTHOR,        ID3FID_INVOLVEDPEOPLE,
-           ENC_TEXT_LIST);
-    // Involved people list
-    insert(Kwave::INF_AUTHOR,        ID3FID_INVOLVEDPEOPLE2,
-           ENC_TEXT_LIST);
-    // Band/orchestra/accompaniment
-    insert(Kwave::INF_AUTHOR,        ID3FID_BAND,
-           ENC_TEXT);
-    // Original lyricist(s)/text writer(s)
-    insert(Kwave::INF_AUTHOR,        ID3FID_ORIGLYRICIST,
-           ENC_TEXT_SLASH);
-    // Official artist/performer webpage
-    insert(Kwave::INF_AUTHOR,        ID3FID_WWWARTIST,
-           ENC_TEXT_URL);
-    // Official publisher webpage
-    insert(Kwave::INF_AUTHOR,        ID3FID_WWWPUBLISHER,
-           ENC_TEXT_URL);
-    //     Kwave::INF_BITRATE_LOWER
-    //     Kwave::INF_BITRATE_NOMINAL
-    //     Kwave::INF_BITRATE_UPPER
-    //     Kwave::INF_BITS_PER_SAMPLE
-    // Part of a set
-    insert(Kwave::INF_CD,            ID3FID_PARTINSET,
-           ENC_TEXT_PARTINSET);
-    insert(Kwave::INF_CDS,           ID3FID_PARTINSET,
-           ENC_TEXT_PARTINSET);
-    // Internet radio station name
-    insert(Kwave::INF_COMMISSIONED,  ID3FID_NETRADIOSTATION,
-           ENC_TEXT);
-    // Internet radio station owner
-    insert(Kwave::INF_COMMISSIONED,  ID3FID_NETRADIOOWNER,
-           ENC_TEXT);
-    // Comments
-    insert(Kwave::INF_COMMENTS,      ID3FID_COMMENT,
-           ENC_COMMENT);
-    // Official audio source webpage
-    insert(Kwave::INF_CONTACT,       ID3FID_WWWAUDIOSOURCE,
-           ENC_TEXT_SLASH);
-    // Official internet radio station homepage
-    insert(Kwave::INF_CONTACT,       ID3FID_WWWRADIOPAGE,
-           ENC_TEXT_SLASH);
-    // Official audio file webpage
-    insert(Kwave::INF_CONTACT,       ID3FID_WWWAUDIOFILE,
-           ENC_TEXT_SLASH);
-    // Ownership (not supported by id3lib)
-    //    (Kwave::INF_CONTACT,       ID3FID_OWNERSHIP,
-    //     ENC_OWNERSHIP?);
-    // Copyright message.
-    insert(Kwave::INF_COPYRIGHT,     ID3FID_COPYRIGHT,
-           ENC_TEXT);
-    // Copyright/Legal information
-    insert(Kwave::INF_COPYRIGHT,     ID3FID_WWWCOPYRIGHT,
-           ENC_TEXT_URL);
-    // Terms of use
-    insert(Kwave::INF_COPYRIGHT,     ID3FID_TERMSOFUSE,
-           ENC_TERMS_OF_USE);
-    //     Kwave::INF_COPYRIGHTED
-
-    // Recording dates
-    insert(Kwave::INF_CREATION_DATE, ID3FID_RECORDINGDATES,
-           ENC_TEXT_TIMESTAMP);
-    // Recording time (not supported by id3lib)
-    //    (Kwave::INF_CREATION_DATE, ID3FID_RECORDINGTIME,
-    //     ENC_TEXT_TIMESTAMP);
-    // Date
-    insert(Kwave::INF_CREATION_DATE, ID3FID_DATE,
-           ENC_TEXT_TIMESTAMP);
-    // Year
-    insert(Kwave::INF_CREATION_DATE, ID3FID_YEAR,
-           ENC_TEXT_TIMESTAMP);
-    // Time
-    insert(Kwave::INF_CREATION_DATE, ID3FID_TIME,
-           ENC_TEXT_TIMESTAMP);
-    // Release time (not supported by id3lib)
-    //    (Kwave::INF_CREATION_DATE, ID3FID_RELEASETIME,
-    //     ENC_TEXT_TIMESTAMP);
-    // Original release year
-    insert(Kwave::INF_CREATION_DATE, ID3FID_ORIGYEAR,
-           ENC_TEXT_TIMESTAMP);
-    // Original release time (not supported by id3lib)
-    //    (Kwave::INF_CREATION_DATE, ID3FID_ORIGRELEASETIME,
-    //     ENC_TEXT_TIMESTAMP);
-    // Tagging time (not supported by id3lib)
-    //    (Kwave::INF_CREATION_DATE, ID3FID_TAGGINGTIME,
-    //     ENC_TEXT_TIMESTAMP);
-    // Encoding time (not supported by id3lib)
-    //    (Kwave::INF_CREATION_DATE, ID3FID_ENCODINGTIME,
-    //     ENC_TEXT_TIMESTAMP);
-
-    //     Kwave::INF_ENGINEER
-    //     Kwave::INF_FILENAME
-    //     Kwave::INF_FILESIZE
-    // Content type (Genre)
-    insert(Kwave::INF_GENRE,         ID3FID_CONTENTTYPE,
-           ENC_GENRE_TYPE);
-    // ISRC
-    // ID3 tags (custom/binary)
-    insert(Kwave::INF_ID3,           ID3FID_NOFRAME,
-           ENC_BINARY);
-    insert(Kwave::INF_ISRC,          ID3FID_ISRC,
-           ENC_TEXT);
-    //     Kwave::INF_KEYWORDS
-    //     Kwave::INF_LABELS
-    // Length
-    insert(Kwave::INF_LENGTH,        ID3FID_SONGLEN,
-           ENC_LENGTH);
-    // File owner/licensee
-    insert(Kwave::INF_LICENSE,       ID3FID_FILEOWNER,
-           ENC_TEXT);
-    // Medium type
-    insert(Kwave::INF_MEDIUM,        ID3FID_MEDIATYPE,
-           ENC_TEXT);
-    //     Kwave::INF_MIMETYPE
-    //     Kwave::INF_MPEG_EMPHASIS
-    //     Kwave::INF_MPEG_LAYER
-    //     Kwave::INF_MPEG_MODEEXT
-    //     Kwave::INF_MPEG_VERSION
-    // Title/songname/content description
-    insert(Kwave::INF_NAME,          ID3FID_TITLE,
-           ENC_TEXT);
-    // Composer
-    insert(Kwave::INF_ORGANIZATION,  ID3FID_COMPOSER,
-           ENC_TEXT_SLASH);
-    // Publisher
-    insert(Kwave::INF_ORGANIZATION,  ID3FID_PUBLISHER,
-           ENC_TEXT_SLASH);
-    // Produced notice
-    insert(Kwave::INF_ORGANIZATION,  ID3FID_PRODUCEDNOTICE,
-           ENC_TEXT_SLASH);
-    //     Kwave::INF_ORIGINAL
-    // Lyricist/Text writer
-    insert(Kwave::INF_PERFORMER,     ID3FID_LYRICIST,
-           ENC_TEXT_SLASH);
-    // Lead performer(s)/Soloist(s).
-    insert(Kwave::INF_PERFORMER,     ID3FID_LEADARTIST,
-           ENC_TEXT_SLASH);
-    // Musician credits list
-    insert(Kwave::INF_PERFORMER,     ID3FID_MUSICIANCREDITLIST,
-           ENC_TEXT_SLASH);
-    // Conductor/performer refinement
-    insert(Kwave::INF_PERFORMER,     ID3FID_CONDUCTOR,
-           ENC_TEXT);
-    // Private frame
-    //     Kwave::INF_PRIVATE
-    //     Kwave::INF_PRODUCT
-    //     Kwave::INF_SAMPLE_FORMAT
-    //     Kwave::INF_SAMPLE_RATE
-    insert(Kwave::INF_SOFTWARE,      ID3FID_ENCODERSETTINGS,
-           ENC_TEXT);
-    //     Kwave::INF_SOURCE
-    //     Kwave::INF_SOURCE_FORM
-    //     Kwave::INF_SUBJECT
-    // Encoded by.
-    insert(Kwave::INF_TECHNICAN,     ID3FID_ENCODEDBY,
-           ENC_TEXT);
-    // Track number/Position in set
-    insert(Kwave::INF_TRACK,         ID3FID_TRACKNUM,
-           ENC_TRACK_NUM);
-    // Number of Tracks
-    insert(Kwave::INF_TRACKS,        ID3FID_TRACKNUM,
-           ENC_TRACK_NUM);
-    //     Kwave::INF_VBR_QUALITY
-    // Interpreted, remixed / modified by
-    insert(Kwave::INF_VERSION,       ID3FID_MIXARTIST,
-           ENC_TEXT);
-    // Set subtitle
-    insert(Kwave::INF_VERSION,       ID3FID_SETSUBTITLE,
-           ENC_TEXT);
-    //                               ID3FID_PRIVATE => user defined data
-
-    insert(Kwave::INF_UNKNOWN,       ID3FID_NOFRAME,
-           ENC_NONE);
-}
-
-//***************************************************************************
-void Kwave::ID3_PropertyMap::insert(const Kwave::FileProperty property,
-    const ID3_FrameID id, const Kwave::ID3_PropertyMap::Encoding encoding)
-{
-    Kwave::ID3_PropertyMap::Mapping mapping;
-
-    mapping.m_property = property;
-    mapping.m_frame_id = id;
-    mapping.m_encoding = encoding;
-    m_list.append(mapping);
-}
-
-//***************************************************************************
-ID3_FrameID Kwave::ID3_PropertyMap::findProperty(
-    const Kwave::FileProperty property) const
-{
-    for(const Kwave::ID3_PropertyMap::Mapping &m : m_list) {
-        if ((m.m_property == property) && supported(m.m_frame_id))
-            return m.m_frame_id;
-    }
-    return ID3FID_NOFRAME;
-}
-
-//***************************************************************************
-bool Kwave::ID3_PropertyMap::containsProperty(
-        const Kwave::FileProperty property) const
-{
-    for(const Kwave::ID3_PropertyMap::Mapping &m : m_list) {
-        if ((m.m_property == property) && supported(m.m_frame_id))
-            return true;
-    }
-    return false;
-}
-
-//***************************************************************************
-bool Kwave::ID3_PropertyMap::containsID(const ID3_FrameID id) const
-{
-    if (!supported(id))
-        return false;
-
-    for(const Kwave::ID3_PropertyMap::Mapping &m : m_list) {
-        if (m.m_frame_id == id)
-            return true;
-    }
-    return false;
-}
-
-//***************************************************************************
-Kwave::ID3_PropertyMap::Encoding Kwave::ID3_PropertyMap::encoding(
-    const ID3_FrameID id) const
-{
-    for (const Kwave::ID3_PropertyMap::Mapping &m : m_list) {
-        if (m.m_frame_id == id)
-            return m.m_encoding;
-    }
-    return ID3_PropertyMap::ENC_NONE;
-}
-
-//***************************************************************************
-QList<ID3_FrameID> Kwave::ID3_PropertyMap::knownIDs() const
-{
-    QList<ID3_FrameID> list;
-    for (const Kwave::ID3_PropertyMap::Mapping &m : m_list) {
-        if (!list.contains(m.m_frame_id))
-            list.append(m.m_frame_id);
-    }
-    return list;
-}
-
-//***************************************************************************
-Kwave::FileProperty Kwave::ID3_PropertyMap::property(const ID3_FrameID id) 
const
-{
-    for (const Kwave::ID3_PropertyMap::Mapping &m : m_list) {
-        if (m.m_frame_id == id) return m.m_property;
-    }
-    return Kwave::INF_UNKNOWN;
-}
-
-//***************************************************************************
-QList<Kwave::FileProperty> Kwave::ID3_PropertyMap::properties() const
-{
-    QList<Kwave::FileProperty> list;
-    for (const Kwave::ID3_PropertyMap::Mapping &m : m_list) {
-        if (!list.contains(m.m_property))
-            list.append(m.m_property);
-    }
-    return list;
-}
-
-//***************************************************************************
-bool Kwave::ID3_PropertyMap::supported(const ID3_FrameID id) const
-{
-    ID3_FrameInfo frameInfo;
-    return (frameInfo.NumFields(id) != 0);
-}
-
-//***************************************************************************
-//***************************************************************************
diff --git a/plugins/codec_mp3/ID3_PropertyMap.h 
b/plugins/codec_mp3/ID3_PropertyMap.h
deleted file mode 100644
index b67ffc6b..00000000
--- a/plugins/codec_mp3/ID3_PropertyMap.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*************************************************************************
-    ID3_PropertyMap.h    -  map for translating properties to ID3 frame tags
-                             -------------------
-    begin                : Sat Jul 30 2012
-    copyright            : (C) 2012 by Thomas Eschenbacher
-    email                : [email protected]
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#ifndef ID3_PROPERTY_MAP_H
-#define ID3_PROPERTY_MAP_H
-
-#include "config.h"
-
-#include <QList>
-
-#include <id3/globals.h>
-
-#include "libkwave/FileInfo.h"
-
-namespace Kwave
-{
-
-    class ID3_PropertyMap
-    {
-    public:
-
-        /** encoding of the ID3 tag */
-        typedef enum {
-            ENC_NONE = 0,
-            ENC_COMMENT,        /**< comment frame                     */
-            ENC_GENRE_TYPE,     /**< genre type, numeric or text       */
-            ENC_LENGTH,         /**< string with length in ms          */
-            ENC_TERMS_OF_USE,   /**< terms of use                      */
-            ENC_TEXT,           /**< text, appended by ';'             */
-            ENC_TEXT_SLASH,     /**< text list, separated by slash '/' */
-            ENC_TEXT_LIST,      /**< list of zero terminated strings   */
-            ENC_TEXT_URL,       /**< URL                               */
-            ENC_TEXT_PARTINSET, /**< part in set (x/y)                 */
-            ENC_TEXT_TIMESTAMP, /**< ISO 8601 timestamp                */
-            ENC_TRACK_NUM,      /**< track/tracks (x/y)                */
-            ENC_BINARY          /**< binary/custom data                */
-        } Encoding;
-
-        /** Default constructor, with initializing */
-        ID3_PropertyMap();
-
-        /** Destructor */
-        virtual ~ID3_PropertyMap() {}
-
-        /**
-         * Returns the frame ID of a property or an empty string
-         * if nothing found (reverse lookup).
-         */
-        ID3_FrameID findProperty(const Kwave::FileProperty property) const;
-
-        /** Returns true if the map contains a given property */
-        bool containsProperty(const Kwave::FileProperty property) const;
-
-        /**
-         * insert a new property / frame ID mapping
-         *
-         * @param property a Kwave FileProperty
-         * @param id a ID3 frame ID
-         * @param encoding the type of the encoding of the tag
-         */
-        void insert(const Kwave::FileProperty property, const ID3_FrameID id,
-                    const Encoding encoding);
-
-        /**
-         * returns true if a given ID3 frame ID is in the map
-         *
-         * @param id a ID3 frame ID
-         * @return true if found, false if not
-         */
-        bool containsID(const ID3_FrameID id) const;
-
-        /**
-         * returns the encoding of the ID3 frame
-         *
-         * @param id a ID3 frame ID
-         * @return the encoding of the content of the frame
-         */
-        Encoding encoding(const ID3_FrameID id) const;
-
-        /** returns a list of all known ID3 frame IDs */
-        QList<ID3_FrameID> knownIDs() const;
-
-        /**
-         * Returns the first FileProperty that matches a given ID3 frame ID
-         *
-         * @param id a ID3 frame ID
-         * @return a FileProperty
-         */
-        Kwave::FileProperty property(const ID3_FrameID id) const;
-
-        /** Returns a list with all supported properties */
-        QList<Kwave::FileProperty> properties() const;
-
-    private:
-
-        /** returns true if a frame is supported by id3lib */
-        bool supported(const ID3_FrameID id) const;
-
-    private:
-        /** container for one mapping */
-        typedef struct
-        {
-            Kwave::FileProperty m_property; /**< the Kwave property */
-            ID3_FrameID  m_frame_id;        /**< ID3 frame ID       */
-            Encoding     m_encoding;        /**< data encoding      */
-        } Mapping;
-
-        /** list of mappings */
-        QList<Mapping> m_list;
-    };
-}
-
-#endif /* ID3_PROPERTY_MAP_H */
-
-//***************************************************************************
-//***************************************************************************
diff --git a/plugins/codec_mp3/ID3_QIODeviceReader.cpp 
b/plugins/codec_mp3/ID3_QIODeviceReader.cpp
deleted file mode 100644
index 065863e9..00000000
--- a/plugins/codec_mp3/ID3_QIODeviceReader.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*************************************************************************
-    ID3_QIODeviceReader.cpp  -  Adapter between QIODevice and ID3_Reader
-                             -------------------
-    begin                : Wed Aug 14 2002
-    copyright            : (C) 2002 by Thomas Eschenbacher
-    email                : [email protected]
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#include "config.h"
-
-#include <QIODevice>
-
-#include "ID3_QIODeviceReader.h"
-
-//***************************************************************************
-Kwave::ID3_QIODeviceReader::ID3_QIODeviceReader(QIODevice &source)
-        :ID3_Reader(), m_source(source)
-{
-}
-
-//***************************************************************************
-Kwave::ID3_QIODeviceReader::~ID3_QIODeviceReader()
-{
-}
-
-//***************************************************************************
-void Kwave::ID3_QIODeviceReader::close()
-{
-}
-
-//***************************************************************************
-ID3_Reader::pos_type Kwave::ID3_QIODeviceReader::getBeg()
-{
-    return 0;
-}
-
-//***************************************************************************
-ID3_Reader::pos_type Kwave::ID3_QIODeviceReader::getEnd()
-{
-    return static_cast<ID3_Reader::pos_type>(m_source.size());
-}
-
-//***************************************************************************
-ID3_Reader::pos_type Kwave::ID3_QIODeviceReader::getCur()
-{
-    return static_cast<ID3_Reader::pos_type>(m_source.pos());
-}
-
-//***************************************************************************
-ID3_Reader::pos_type Kwave::ID3_QIODeviceReader::setCur(
-    ID3_Reader::pos_type pos)
-{
-    if (!m_source.seek(static_cast<qint64>(pos)))
-        return static_cast<ID3_Reader::pos_type>(-1);
-    return static_cast<ID3_Reader::pos_type>(m_source.pos());
-}
-
-//***************************************************************************
-ID3_Reader::int_type Kwave::ID3_QIODeviceReader::readChar()
-{
-    unsigned char c = 0;
-    m_source.getChar(reinterpret_cast<char *>(&c));
-    return static_cast<ID3_Reader::int_type>(c);
-}
-
-//***************************************************************************
-ID3_Reader::int_type Kwave::ID3_QIODeviceReader::peekChar()
-{
-    qint64 pos = m_source.pos();
-    ID3_Reader::int_type ch = readChar();
-    m_source.seek(pos);
-    return ch;
-}
-
-//***************************************************************************
-ID3_Reader::size_type Kwave::ID3_QIODeviceReader::readChars(
-    char_type buf[], size_type len)
-{
-     qint64 size = m_source.read(
-        reinterpret_cast<char *>(&(buf[0])),
-        static_cast<qint64>(len)
-    );
-    return static_cast<ID3_Reader::size_type>(size);
-}
-
-//***************************************************************************
-ID3_Reader::size_type Kwave::ID3_QIODeviceReader::readChars(
-    char buf[], size_type len)
-{
-    return this->readChars(reinterpret_cast<char_type *>(buf), len);
-}
-
-//***************************************************************************
-//***************************************************************************
diff --git a/plugins/codec_mp3/ID3_QIODeviceReader.h 
b/plugins/codec_mp3/ID3_QIODeviceReader.h
deleted file mode 100644
index de1be79b..00000000
--- a/plugins/codec_mp3/ID3_QIODeviceReader.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*************************************************************************
-    ID3_QIODeviceReader.h  -  Adapter between QIODevice and ID3_Reader
-                             -------------------
-    begin                : Wed Aug 14 2002
-    copyright            : (C) 2002 by Thomas Eschenbacher
-    email                : [email protected]
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#ifndef ID3_QIODEVICE_READER_H
-#define ID3_QIODEVICE_READER_H
-
-#include "config.h"
-
-#include <id3/globals.h>
-#include <id3/reader.h>
-
-class QIODevice;
-
-namespace Kwave
-{
-    /**
-     * @class ID3_QIODeviceReader
-     * Adapter between QIODevice and ID3_Reader
-     */
-    class ID3_QIODeviceReader: public ID3_Reader
-    {
-    public:
-
-        /** Constructor */
-        explicit ID3_QIODeviceReader(QIODevice &source);
-
-        /** Destructor */
-        virtual ~ID3_QIODeviceReader();
-
-        /** Close the source. Not implemented. */
-        void close() override;
-
-        /** Get the start position, always zero */
-        ID3_Reader::pos_type getBeg() override;
-
-        /** Get the end position, identical to size()-1 */
-        ID3_Reader::pos_type getEnd() override;
-
-        /** Returns the current position */
-        ID3_Reader::pos_type getCur() override;
-
-        /** Sets a new position and returns the new one */
-        virtual ID3_Reader::pos_type setCur(ID3_Reader::pos_type pos = 0)
-            override;
-
-        /** Reads out one single character */
-        ID3_Reader::int_type readChar() override;
-
-        /** Reads one character without advancing the current position */
-        ID3_Reader::int_type peekChar() override;
-
-        /** Read out a block of characters */
-        virtual size_type readChars(char_type buf[], size_type len)
-            override;
-        virtual size_type readChars(char buf[], size_type len)
-            override;
-
-    private:
-
-        /** reference to a QIODevice that is used as source */
-        QIODevice &m_source;
-    };
-}
-
-#endif /* ID3_QIODEVICE_READER_H */
-
-//***************************************************************************
-//***************************************************************************
diff --git a/plugins/codec_mp3/ID3_QIODeviceWriter.cpp 
b/plugins/codec_mp3/ID3_QIODeviceWriter.cpp
deleted file mode 100644
index 0e315434..00000000
--- a/plugins/codec_mp3/ID3_QIODeviceWriter.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*************************************************************************
-    ID3_QIODeviceWriter.cpp  -  Adapter between QIODevice and ID3_Writer
-                             -------------------
-    begin                : Mon May 28 2012
-    copyright            : (C) 2012 by Thomas Eschenbacher
-    email                : [email protected]
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#include "config.h"
-
-#include <QIODevice>
-
-#include "ID3_QIODeviceWriter.h"
-
-//***************************************************************************
-Kwave::ID3_QIODeviceWriter::ID3_QIODeviceWriter(QIODevice &dest)
-    :ID3_Writer(), m_dest(dest), m_written(0)
-{
-}
-
-//***************************************************************************
-Kwave::ID3_QIODeviceWriter::~ID3_QIODeviceWriter()
-{
-}
-
-//***************************************************************************
-void Kwave::ID3_QIODeviceWriter::close()
-{
-}
-
-//***************************************************************************
-void Kwave::ID3_QIODeviceWriter::flush()
-{
-}
-
-//***************************************************************************
-ID3_Writer::pos_type Kwave::ID3_QIODeviceWriter::getBeg()
-{
-    return 0;
-}
-
-//***************************************************************************
-ID3_Writer::pos_type Kwave::ID3_QIODeviceWriter::getEnd()
-{
-    return getMaxSize();
-}
-
-//***************************************************************************
-ID3_Writer::pos_type Kwave::ID3_QIODeviceWriter::getCur()
-{
-    return m_written;
-}
-
-//***************************************************************************
-ID3_Writer::size_type Kwave::ID3_QIODeviceWriter::getSize()
-{
-    return m_written;
-}
-
-//***************************************************************************
-ID3_Writer::size_type Kwave::ID3_QIODeviceWriter::getMaxSize()
-{
-    return (1U << ((sizeof(ID3_Writer::size_type) * 8) - 1));
-}
-
-//***************************************************************************
-ID3_Writer::size_type Kwave::ID3_QIODeviceWriter::writeChars(
-            const ID3_Writer::char_type buf[], ID3_Writer::size_type len)
-{
-    return this->writeChars(reinterpret_cast<const char *>(buf), len);
-}
-
-//***************************************************************************
-ID3_Writer::size_type Kwave::ID3_QIODeviceWriter::writeChars(
-            const char buf[], ID3_Writer::size_type len)
-{
-    ID3_Writer::size_type bytes =  static_cast<ID3_Writer::size_type>(
-        m_dest.write(&(buf[0]), static_cast<qint64>(len)));
-    if (bytes > 0)
-        m_written += bytes;
-    return bytes;
-}
-
-//***************************************************************************
-bool Kwave::ID3_QIODeviceWriter::atEnd()
-{
-    return false;
-}
-
-//***************************************************************************
-//***************************************************************************
diff --git a/plugins/codec_mp3/ID3_QIODeviceWriter.h 
b/plugins/codec_mp3/ID3_QIODeviceWriter.h
deleted file mode 100644
index 2ab9ce88..00000000
--- a/plugins/codec_mp3/ID3_QIODeviceWriter.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*************************************************************************
-  ID3_QIODeviceWriter.h  -  Adapter between QIODevice and ID3_Writer
-                             -------------------
-    begin                : Mon May 28 2012
-    copyright            : (C) 2012 by Thomas Eschenbacher
-    email                : [email protected]
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#ifndef ID3_QIODEVICE_WRITER_H
-#define ID3_QIODEVICE_WRITER_H
-
-#include "config.h"
-
-#include <id3/globals.h>
-#include <id3/writer.h>
-
-class QIODevice;
-
-namespace Kwave
-{
-    /**
-     * @class ID3_QIODeviceWriter
-     * Adapter between QIODevice and ID3_Writer
-     */
-    class ID3_QIODeviceWriter: public ID3_Writer
-    {
-    public:
-
-        /** Constructor */
-        explicit ID3_QIODeviceWriter(QIODevice &dest);
-
-        /** Destructor */
-        virtual ~ID3_QIODeviceWriter();
-
-        /** Close the destination. Not implemented. */
-        void close() override;
-
-        /** Flush the destination, not implemented (not needed) */
-        void flush() override;
-
-        /** Get the start position, always zero */
-        ID3_Writer::pos_type getBeg() override;
-
-        /** Get the end position, identical to size()-1 */
-        ID3_Writer::pos_type getEnd() override;
-
-        /** Returns the current position */
-        ID3_Writer::pos_type getCur() override;
-
-        /** Returns the number of bytes written */
-        ID3_Writer::size_type getSize() override;
-
-        /** Returns the maximum number of bytes written */
-        ID3_Writer::size_type getMaxSize() override;
-
-        /**
-         * Write up to len characters into buf and advance the internal 
position
-         * accordingly.
-         */
-        virtual ID3_Writer::size_type writeChars(
-            const ID3_Writer::char_type buf[], ID3_Writer::size_type len)
-            override;
-
-        virtual ID3_Writer::size_type writeChars(
-            const char buf[], ID3_Writer::size_type len)
-            override;
-
-        /** returns true if the writer has read eof (always false) */
-        bool atEnd() override;
-
-    private:
-
-        /** reference to a QIODevice that is used as destination */
-        QIODevice &m_dest;
-
-        /** number of bytes written */
-        ID3_Writer::size_type m_written;
-    };
-}
-
-#endif /* ID3_QIODEVICE_WRITER_H */
-
-//***************************************************************************
-//***************************************************************************
diff --git a/plugins/codec_mp3/MP3Encoder.cpp b/plugins/codec_mp3/MP3Encoder.cpp
index c4bab547..ec5d61cb 100644
--- a/plugins/codec_mp3/MP3Encoder.cpp
+++ b/plugins/codec_mp3/MP3Encoder.cpp
@@ -20,9 +20,9 @@
 #include <math.h>
 #include <new>
 
-#include <id3/globals.h>
-#include <id3/misc_support.h>
-#include <id3/tag.h>
+#include <taglib/commentsframe.h>
+#include <taglib/textidentificationframe.h>
+#include <taglib/unknownframe.h>
 
 #include <QBuffer>
 #include <QByteArray>
@@ -45,11 +45,10 @@
 #include "libkwave/String.h"
 #include "libkwave/Utils.h"
 
-#include "ID3_QIODeviceReader.h"
-#include "ID3_QIODeviceWriter.h"
 #include "MP3CodecPlugin.h"
 #include "MP3Encoder.h"
 #include "MP3EncoderSettings.h"
+#include "TagLib_PropertyMap.h"
 
 /***************************************************************************/
 Kwave::MP3Encoder::MP3Encoder()
@@ -96,223 +95,270 @@ QList<Kwave::FileProperty> 
Kwave::MP3Encoder::supportedProperties()
 
 /***************************************************************************/
 void Kwave::MP3Encoder::encodeID3Tags(const Kwave::MetaDataList &meta_data,
-                                      ID3_Tag &tag)
+                                      TagLib::ID3v2::Tag &tag)
 {
+    // encode meta data with taglib
     const Kwave::FileInfo info(meta_data);
+    const QMap<Kwave::FileProperty, QVariant> props = info.properties();
 
-    const QMap<Kwave::FileProperty, QVariant> properties(info.properties());
-    QMap<Kwave::FileProperty, QVariant>::const_iterator it;
-    for (it = properties.begin(); it != properties.end(); ++it) {
-        const Kwave::FileProperty &property = it.key();
-        const QVariant            &value    = it.value();
-
-        ID3_FrameID id = m_property_map.findProperty(property);
-        if ((property != Kwave::FileProperty::INF_ID3) &&
-            (id == ID3FID_NOFRAME)) continue;
-
-        if (info.contains(Kwave::INF_CD) && (property == Kwave::INF_CDS))
-            continue; /* INF_CDS has already been handled by INF_CD */
-        if (info.contains(Kwave::INF_TRACK) && (property == Kwave::INF_TRACKS))
-            continue; /* INF_TRACKS has already been handled by INF_TRACK */
-
-        ID3_Frame *frame = new(std::nothrow) ID3_Frame;
-        Q_ASSERT(frame);
-        if (!frame) break;
-
-        QString str_val = value.toString();
-//      qDebug("encoding ID3 tag #%02d, property='%s', value='%s'",
-//          static_cast<int>(id),
-//          DBG(info.name(property)),
-//          DBG(str_val)
-//      );
-
-        // encode in UCS16
-        frame->SetID(id);
-        ID3_Field *field = frame->GetField(ID3FN_TEXT);
-        if ((property != Kwave::FileProperty::INF_ID3) && !field) {
-            qWarning("no field, frame id=%d", static_cast<int>(id));
-            delete frame;
+    for (auto it = props.constBegin(); it != props.constEnd(); ++it)
+    {
+        const Kwave::FileProperty prop = it.key();
+
+        // skip separate total track count if already merged into TRCK
+        if ((prop == Kwave::INF_TRACKS) && info.contains(Kwave::INF_TRACK))
+            continue;
+
+        // skip separate total cd count if already merged into TPOS
+        if ((prop == Kwave::INF_CDS) && info.contains(Kwave::INF_CD))
+            continue;
+
+        const TagLib::ByteVector frame_id = m_property_map.findProperty(prop);
+        if (frame_id.isEmpty())
             continue;
-        }
 
-        bool ok = true;
-        ID3_PropertyMap::Encoding encoding = m_property_map.encoding(id);
-        switch (encoding) {
-            case ID3_PropertyMap::ENC_TEXT_PARTINSET:
+        const TagLib_PropertyMap::Encoding enc =
+            m_property_map.encoding(frame_id);
+        switch (enc)
+        {
+            case TagLib_PropertyMap::ENC_COMMENT:
             {
-                field->SetEncoding(ID3TE_UTF16);
+                // create comment frame with language code
+                const QStringList list = it.value().toStringList();
+                for (QString c : list)
+                {
+                    if (c.isEmpty())
+                        continue;
 
-                // if "number of CDs" is available: append with "/"
-                int cds = info.get(Kwave::INF_CDS).toInt();
-                if (cds > 0)
-                    str_val += _("/%1").arg(cds);
+                    TagLib::ByteVector lang("eng", 3);
+                    if ((c.length() > 5) &&
+                        (c.at(0) == QLatin1Char('[')) &&
+                        (c.at(4) == QLatin1Char(']')))
+                    {
+                        const QString l = c.mid(1, 3);
+                        lang = TagLib::ByteVector(l.toLatin1().constData(), 3);
+                        c = c.mid(5).trimmed();
+                    }
 
-                field->Set(static_cast<const unicode_t *>(str_val.utf16()));
+                    TagLib::ID3v2::CommentsFrame *frame =
+                    new(std::nothrow) TagLib::ID3v2::CommentsFrame(
+                        TagLib::String::UTF8);
+                    if (!frame)
+                        continue;
+
+                    frame->setLanguage(lang);
+                    frame->setText(
+                        TagLib::String(c.toUtf8().constData(),
+                                       TagLib::String::UTF8));
+                    tag.addFrame(frame);
+                }
                 break;
             }
-            case ID3_PropertyMap::ENC_TRACK_NUM:
+            case TagLib_PropertyMap::ENC_TRACK_NUM:
             {
-                // if "number of tracks" is available: append with "/"
-                int tracks = info.get(Kwave::INF_TRACKS).toInt();
-                if (tracks > 0)
-                    str_val += _("/%1").arg(tracks);
+                // format track number as "track/total" if total tracks count
+                QString val = it.value().toString();
+                if (val.isEmpty())
+                    break;
 
-                field->SetEncoding(ID3TE_UTF16);
-                field->Set(static_cast<const unicode_t *>(str_val.utf16()));
+                if ((prop == Kwave::INF_TRACK) && 
info.contains(Kwave::INF_TRACKS))
+                {
+                    const QString total = 
info.get(Kwave::INF_TRACKS).toString();
+                    if (!total.isEmpty())
+                        val += QLatin1Char('/') + total;
+                }
+
+                TagLib::ID3v2::TextIdentificationFrame *frame =
+                new(std::nothrow) TagLib::ID3v2::TextIdentificationFrame(
+                    frame_id, TagLib::String::UTF8);
+                if (!frame)
+                    break;
+
+                frame->setText(
+                    TagLib::String(val.toUtf8().constData(),
+                                   TagLib::String::UTF8));
+                tag.addFrame(frame);
                 break;
             }
-            case ID3_PropertyMap::ENC_TERMS_OF_USE:
-                // the same as ENC_COMMENT, but without "Description"
-                /* FALLTHROUGH */
-            case ID3_PropertyMap::ENC_COMMENT:
+            case TagLib_PropertyMap::ENC_TEXT_PARTINSET:
             {
-                ok = false;
-                QStringList list = info.get(property).toStringList();
-                for (QString c : list)
-                {
-                    delete frame;
-                    frame = new(std::nothrow) ID3_Frame;
-                    Q_ASSERT(frame != nullptr);
-                    if (frame == nullptr) continue;
-                    frame->SetID(id);
-
-                    // detect language at the start "[xxx] "
-                    if ( (c.length() > 5) &&
-                         (c.at(0) == QLatin1Char('[')) &&
-                         (c.at(4) == QLatin1Char(']')) ) {
-                        QString lang = c.mid(1,3);
-                        c      = c.mid(5).trimmed();
-                        frame->GetField(ID3FN_LANGUAGE)->Set(
-                            static_cast<const char *>(lang.toLatin1().data()));
-                    }
-                    /* frame->GetField(ID3FN_DESCRIPTION)->Set("..."); */
-                    field = frame->GetField(ID3FN_TEXT);
-                    if (field) {
-                        field->SetEncoding(ID3TE_UTF16);
-                        field->Set(static_cast<const unicode_t *>(c.utf16()));
-                    }
+                // format disc number as "disc/total" if total discs count
+                QString val = it.value().toString();
+                if (val.isEmpty())
+                    break;
 
-                    if (tag.AttachFrame(frame)) {
-                        frame = nullptr;
-                        ok = true;
-                    }
+                if ((prop == Kwave::INF_CD) && info.contains(Kwave::INF_CDS))
+                {
+                    const QString total = info.get(Kwave::INF_CDS).toString();
+                    if (!total.isEmpty())
+                        val += QLatin1Char('/') + total;
                 }
+
+                TagLib::ID3v2::TextIdentificationFrame *frame =
+                new(std::nothrow) TagLib::ID3v2::TextIdentificationFrame(
+                    frame_id, TagLib::String::UTF8);
+                if (!frame)
+                    break;
+
+                frame->setText(
+                    TagLib::String(val.toUtf8().constData(),
+                                   TagLib::String::UTF8));
+                tag.addFrame(frame);
                 break;
             }
-            case ID3_PropertyMap::ENC_GENRE_TYPE:
+            case TagLib_PropertyMap::ENC_GENRE_TYPE:
             {
-                int genre = Kwave::GenreType::fromID3(str_val);
-                if (genre >= 0)
-                    str_val = Kwave::GenreType::name(genre, false);
-                // else: user defined genre type, take it as it is
+                // format genre name from numerical id if known
+                QString val = it.value().toString();
+                if (val.isEmpty())
+                    break;
 
-                field->SetEncoding(ID3TE_UTF16);
-                field->Set(static_cast<const unicode_t *>(str_val.utf16()));
+                const int genre = Kwave::GenreType::fromID3(val);
+                if (genre >= 0)
+                    val = Kwave::GenreType::name(genre, false);
+
+                TagLib::ID3v2::TextIdentificationFrame *frame =
+                new(std::nothrow) TagLib::ID3v2::TextIdentificationFrame(
+                    frame_id, TagLib::String::UTF8);
+                if (!frame)
+                    break;
+
+                frame->setText(
+                    TagLib::String(val.toUtf8().constData(),
+                                   TagLib::String::UTF8));
+                tag.addFrame(frame);
                 break;
             }
-            case ID3_PropertyMap::ENC_LENGTH:
+            case TagLib_PropertyMap::ENC_TEXT_TIMESTAMP:
             {
-                // length in milliseconds
-                const double         rate    = info.rate();
-                const sample_index_t samples = info.length();
-                if ((rate > 0) && samples) {
-                    const sample_index_t ms = static_cast<sample_index_t>(
-                        (static_cast<double>(samples) * 1E3) / rate);
-
-                    str_val = QString::number(ms);
-
-                    field->SetEncoding(ID3TE_UTF16);
-                    field->Set(static_cast<const unicode_t 
*>(str_val.utf16()));
-                } else
-                    ok = false;
+                // format timestamp or year
+                const QString val = it.value().toString();
+                if (val.isEmpty())
+                    break;
+
+                QString s = Kwave::string2date(val);
+                if (s.isEmpty())
+                {
+                    const int year = val.toInt();
+                    if ((year > 0) && (year < 9999))
+                        s = _("%1").arg(year, 4, 10, QLatin1Char('0'));
+                }
+                if (s.isEmpty())
+                    break;
+
+                TagLib::ID3v2::TextIdentificationFrame *frame =
+                new(std::nothrow) TagLib::ID3v2::TextIdentificationFrame(
+                    frame_id, TagLib::String::UTF8);
+                if (!frame)
+                    break;
+
+                frame->setText(
+                    TagLib::String(s.toUtf8().constData(),
+                                   TagLib::String::UTF8));
+                tag.addFrame(frame);
                 break;
             }
-            case ID3_PropertyMap::ENC_TEXT_TIMESTAMP:
+            case TagLib_PropertyMap::ENC_TEXT_LIST:      /* FALLTHROUGH */
+            case TagLib_PropertyMap::ENC_TEXT_SLASH:
             {
-                // ISO 8601 timestamp: "yyyy-MM-ddTHH:mm:ss"
-                QString s = Kwave::string2date(str_val);
-
-                // if failed, try "yyyy" format (year only)
-                if (!s.length()) {
-                    int year = str_val.toInt();
-                    if ((year > 0) && (year < 9999)) {
-                        frame->SetID(ID3FID_YEAR);
-                        // -> re-get the field !
-                        // it has become invalid through "SetID()"
-                        field = frame->GetField(ID3FN_TEXT);
-                        if (!field) {
-                            qWarning("no field, frame id=%d",
-                                     static_cast<int>(id));
-                            ok = false;
-                            break;
-                        }
-                        s = _("%1").arg(year, 4, 10, QLatin1Char('0'));
-                    }
+                // create text identification frame with list of strings
+                const QStringList list = it.value().toStringList();
+                if (list.isEmpty())
+                    break;
+
+                TagLib::ID3v2::TextIdentificationFrame *frame =
+                new(std::nothrow) TagLib::ID3v2::TextIdentificationFrame(
+                    frame_id, TagLib::String::UTF8);
+                if (!frame)
+                    break;
+
+                TagLib::StringList taglib_list;
+                for (const QString &item : list)
+                {
+                    if (!item.isEmpty())
+                        taglib_list.append(
+                            TagLib::String(item.toUtf8().constData(),
+                                           TagLib::String::UTF8));
                 }
-
-                if (s.length()) {
-                    field->SetEncoding(ID3TE_UTF16);
-                    field->Set(static_cast<const unicode_t *>(s.utf16()));
-                } else {
-                    // date is invalid, unknown format
-                    qWarning("MP3Encoder::encodeID3Tags(): invalid date: '%s'",
-                             DBG(str_val));
-                    ok = false;
+                if (taglib_list.isEmpty())
+                {
+                    delete frame;
+                    break;
                 }
+
+                frame->setText(taglib_list);
+                tag.addFrame(frame);
                 break;
             }
-            case ID3_PropertyMap::ENC_TEXT_SLASH: /* FALLTHROUGH */
-            case ID3_PropertyMap::ENC_TEXT_URL:   /* FALLTHROUGH */
-            case ID3_PropertyMap::ENC_TEXT:
-                field->SetEncoding(ID3TE_UTF16);
-                field->Set(static_cast<const unicode_t *>(str_val.utf16()));
+            case TagLib_PropertyMap::ENC_TEXT:           /* FALLTHROUGH */
+            case TagLib_PropertyMap::ENC_TEXT_URL:
+            {
+                // create text identification frame
+                const QString val = it.value().toString();
+                if (val.isEmpty())
+                    break;
+
+                TagLib::ID3v2::TextIdentificationFrame *frame =
+                    new(std::nothrow) TagLib::ID3v2::TextIdentificationFrame(
+                        frame_id, TagLib::String::UTF8);
+                if (!frame)
+                    break;
+
+                frame->setText(
+                    TagLib::String(val.toUtf8().constData(),
+                                   TagLib::String::UTF8));
+                tag.addFrame(frame);
                 break;
-            case ID3_PropertyMap::ENC_BINARY:
+            }
+            case TagLib_PropertyMap::ENC_BINARY:
             {
-                QStringList frames = value.toStringList();
-                for (const QString &f : frames) {
-                    delete frame;
-                    frame = new(std::nothrow) ID3_Frame;
-                    Q_ASSERT(frame != nullptr);
-                    if (frame == nullptr) continue;
-
-                    QByteArray raw = QByteArray::fromBase64(f.toLocal8Bit());
-                    QBuffer buffer(&raw);
-                    buffer.open(QIODevice::ReadOnly);
-                    Kwave::ID3_QIODeviceReader reader(buffer);
-                    if (!frame->Parse(reader)) {
-                        qWarning("MP3Encoder::encodeID3Tags(): "
-                        "parsing ENC_BINARY failed");
-                        ok = false;
+                // add raw binary data frame(s) from base64 string list
+                const QStringList frames = it.value().toStringList();
+                for (const QString &f : frames)
+                {
+                    const QByteArray data = 
QByteArray::fromBase64(f.toLatin1());
+                    if (data.isEmpty())
                         continue;
-                    }
-                    qDebug("attaching custom ID3 frame '%s'",
-                           frame->GetDescription());
-                    if (tag.AttachFrame(frame)) {
-                        frame = nullptr;
-                        ok = true;
-                    } else {
-                        qWarning("MP3Encoder::encodeID3Tags(): "
-                        "attaching ENC_BINARY frame failed");
-                        ok = false;
+
+                    TagLib::ID3v2::UnknownFrame *frame =
+                        new(std::nothrow) 
TagLib::ID3v2::UnknownFrame(frame_id);
+                    if (!frame)
                         continue;
-                    }
+
+                    const unsigned int len =
+                        static_cast<unsigned int>(data.size());
+                    frame->setData(TagLib::ByteVector(data.constData(), len));
+                    tag.addFrame(frame);
                 }
                 break;
             }
-            case ID3_PropertyMap::ENC_NONE: /* FALLTHROUGH */
+            case TagLib_PropertyMap::ENC_TERMS_OF_USE:
+            {
+                // add terms of use text frame
+                const QString val = it.value().toString();
+                if (val.isEmpty())
+                    break;
+
+                TagLib::ID3v2::UnknownFrame *frame =
+                    new(std::nothrow) TagLib::ID3v2::UnknownFrame(frame_id);
+                if (!frame)
+                    break;
+
+                const QByteArray utf8 = val.toUtf8();
+                const unsigned int len =
+                    static_cast<unsigned int>(utf8.size());
+                TagLib::ByteVector payload;
+                payload.append('\x03');
+                payload.append(TagLib::ByteVector("eng", 3));
+                payload.append(TagLib::ByteVector(utf8.constData(), len));
+                frame->setData(payload);
+                tag.addFrame(frame);
+                break;
+            }
             default:
-                ok = false;
-                break; // ignore
+                break;
         }
-
-        if (frame && ok) tag.AttachFrame(frame);
-        if (!ok) delete frame;
-        frame = nullptr;
     }
-
-    tag.Strip();
-    tag.Update();
 }
 
 #define OPTION(__field__) \
@@ -329,14 +375,11 @@ bool Kwave::MP3Encoder::encode(QWidget *widget, 
Kwave::MultiTrackReader &src,
                                const Kwave::MetaDataList &meta_data)
 {
     bool result = true;
-    ID3_Tag id3_tag;
+    TagLib::ID3v2::Tag id3_tag;
     Kwave::MP3EncoderSettings settings;
 
     settings.load();
 
-    ID3_TagType id3_tag_type = ID3TT_ID3V2;
-    id3_tag.SetSpec(ID3V2_LATEST);
-
     const Kwave::FileInfo info(meta_data);
 
     // get info: tracks, sample rate
@@ -371,9 +414,11 @@ bool Kwave::MP3Encoder::encode(QWidget *widget, 
Kwave::MultiTrackReader &src,
     m_dst  = &dst;
     m_params.clear();
 
-    // encode meta data into with id3lib
-    ID3_QIODeviceWriter id3_writer(dst);
+    // encode meta data with taglib and write id3v2 header to stream
     encodeID3Tags(meta_data, id3_tag);
+    const TagLib::ByteVector tag_data = id3_tag.render();
+    if (!tag_data.isEmpty())
+        dst.write(tag_data.data(), tag_data.size());
 
     OPTION(m_flags.m_prepend);          // optional parameters at the very 
start
 
@@ -488,10 +533,6 @@ bool Kwave::MP3Encoder::encode(QWidget *widget, 
Kwave::MultiTrackReader &src,
         result = false;
     }
 
-    // if a ID3v2 tag is requested, the tag comes at the start
-    if (id3_tag_type == ID3TT_ID3V2)
-        id3_tag.Render(id3_writer, id3_tag_type);
-
     // MP3 supports only mono and stereo, prepare a mixer matrix
     // (not used in case of tracks <= 2)
     Kwave::MixerMatrix mixer(tracks, out_tracks);
@@ -616,10 +657,6 @@ bool Kwave::MP3Encoder::encode(QWidget *widget, 
Kwave::MultiTrackReader &src,
         ));
     }
 
-    // if a ID3v1 tag is requested, the tag comes at the end
-    if (id3_tag_type != ID3TT_ID3V2)
-        id3_tag.Render(id3_writer, id3_tag_type);
-
     {
         QMutexLocker _lock(&m_lock);
         m_dst = nullptr;
diff --git a/plugins/codec_mp3/MP3Encoder.h b/plugins/codec_mp3/MP3Encoder.h
index 13a3d241..baf925ad 100644
--- a/plugins/codec_mp3/MP3Encoder.h
+++ b/plugins/codec_mp3/MP3Encoder.h
@@ -22,15 +22,17 @@
 
 #include <climits>
 
+#include <taglib/id3v2tag.h>
+#include <taglib/tag.h>
+
 #include <QList>
 #include <QMutex>
 #include <QProcess>
 
 #include "libkwave/Encoder.h"
 
-#include "ID3_PropertyMap.h"
+#include "TagLib_PropertyMap.h"
 
-class ID3_Tag;
 class QIODevice;
 class QWidget;
 
@@ -88,12 +90,12 @@ namespace Kwave
          * @param tag the ID3 tag to receive the ID3 frames
          */
         void encodeID3Tags(const Kwave::MetaDataList &meta_data,
-                           ID3_Tag &tag);
+                           TagLib::ID3v2::Tag &tag);
 
     private:
 
         /** property - to - ID3 mapping */
-        ID3_PropertyMap m_property_map;
+        TagLib_PropertyMap m_property_map;
 
         /** lock for protecting m_dst and m_process */
         QMutex m_lock;

Reply via email to