[multimedia/kwave/5-codec_mp3-broken-id3-tags-due-to-id3lib-bad-handling-of-utf-16] plugins/codec_mp3: codec_mp3: workaround for broken MBS conversion in ID3LIB

Thomas Eschenbacher <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit a98c47b39a936e844fa250673c7a871b8dfe9207 by Thomas Eschenbacher.
Committed on 15/08/2026 at 08:41.
Pushed by eschenbacher into branch '5-codec_mp3-broken-id3-tags-due-to-id3lib-bad-handling-of-utf-16'.

codec_mp3: workaround for broken MBS conversion in ID3LIB

M  +57   -6    plugins/codec_mp3/MP3Decoder.cpp
M  +6    -5    plugins/codec_mp3/MP3Encoder.cpp

https://invent.kde.org/multimedia/kwave/-/commit/a98c47b39a936e844fa250673c7a871b8dfe9207

diff --git a/plugins/codec_mp3/MP3Decoder.cpp b/plugins/codec_mp3/MP3Decoder.cpp
index ea56a1b4..74568685 100644
--- a/plugins/codec_mp3/MP3Decoder.cpp
+++ b/plugins/codec_mp3/MP3Decoder.cpp
@@ -32,6 +32,7 @@
 #include <QDateTime>
 #include <QIODevice>
 #include <QLatin1Char>
+#include <QStringView>
 #include <QTime>
 
 #include "libkwave/Compression.h"
@@ -416,13 +417,63 @@ bool Kwave::MP3Decoder::parseID3Tags(ID3_Tag &tag)
 //***************************************************************************
 QString Kwave::MP3Decoder::parseId3Frame2String(const ID3_Frame *frame)
 {
-    QString s;
-    char *text = ID3_GetString(frame, ID3FN_TEXT);
-    if (text && strlen(text)) {
-        s = _(text);
-        ID3_FreeString(text);
+    if (!frame) return QString();
+
+    // retrieve the encoding field from the ID3 frame
+    ID3_TextEnc enc = ID3TE_NONE;
+    const ID3_Field *enc_field = frame->GetField(ID3FN_TEXTENC);
+    if (enc_field != nullptr)
+        enc = static_cast<ID3_TextEnc>(enc_field->Get());
+
+    switch (enc) {
+        case ID3TE_UTF16: /* FALLTHROUGH */
+        case ID3TE_UTF16BE: {
+            // read raw unicode text directly to bypass id3lib's broken
+            // mbs conversion
+            const ID3_Field *field = frame->GetField(ID3FN_TEXT);
+            if (field != nullptr) {
+                const size_t num_chars = field->GetNumTextItems();
+                if (num_chars > 0) {
+                    const char16_t *uc16_data =
+                        reinterpret_cast<const char16_t *>(
+                            field->GetRawText());
+                    const size_t size_in_bytes = field->Size();
+                    if ((uc16_data != nullptr) && (size_in_bytes > 0)) {
+                        const size_t max_chars =
+                            size_in_bytes / sizeof(char16_t);
+                        const qsizetype pos =
+                            QStringView(uc16_data, max_chars).indexOf(u'\0');
+                        const qsizetype len = (pos >= 0) ? pos :
+                            static_cast<qsizetype>(max_chars);
+                        return QString::fromUtf16(uc16_data, len).trimmed();
+                    }
+                }
+            }
+            break;
+        }
+        case ID3TE_UTF8: {
+            char *text = ID3_GetString(frame, ID3FN_TEXT);
+            if (text != nullptr) {
+                QString result = QString::fromUtf8(text).trimmed();
+                ID3_FreeString(text);
+                return result;
+            }
+            break;
+        }
+        case ID3TE_ISO8859_1: /* FALLTHROUGH */
+        case ID3TE_NONE:      /* FALLTHROUGH */
+        default: {
+            char *text = ID3_GetString(frame, ID3FN_TEXT);
+            if (text != nullptr) {
+                QString result = QString::fromLatin1(text).trimmed();
+                ID3_FreeString(text);
+                return result;
+            }
+            break;
+        }
     }
-    return s;
+
+    return QString();
 }
 
 //***************************************************************************
diff --git a/plugins/codec_mp3/MP3Encoder.cpp b/plugins/codec_mp3/MP3Encoder.cpp
index 942ee845..77a681eb 100644
--- a/plugins/codec_mp3/MP3Encoder.cpp
+++ b/plugins/codec_mp3/MP3Encoder.cpp
@@ -90,7 +90,6 @@ void Kwave::MP3Encoder::encodeID3Tags(const Kwave::MetaDataList &meta_data,
                                       ID3_Tag &tag)
 {
     const Kwave::FileInfo info(meta_data);
-    ID3_FrameInfo frameInfo;
 
     const QMap<Kwave::FileProperty, QVariant> properties(info.properties());
     QMap<Kwave::FileProperty, QVariant>::const_iterator it;
@@ -134,7 +133,7 @@ void Kwave::MP3Encoder::encodeID3Tags(const Kwave::MetaDataList &meta_data,
             {
                 field->SetEncoding(ID3TE_UTF16);
 
-                // if "number of CDs is available: append with "/"
+                // if "number of CDs" is available: append with "/"
                 int cds = info.get(Kwave::INF_CDS).toInt();
                 if (cds > 0)
                     str_val += _("/%1").arg(cds);
@@ -144,7 +143,7 @@ void Kwave::MP3Encoder::encodeID3Tags(const Kwave::MetaDataList &meta_data,
             }
             case ID3_PropertyMap::ENC_TRACK_NUM:
             {
-                // if "number of tracks is available: append with "/"
+                // if "number of tracks" is available: append with "/"
                 int tracks = info.get(Kwave::INF_TRACKS).toInt();
                 if (tracks > 0)
                     str_val += _("/%1").arg(tracks);
@@ -179,8 +178,10 @@ void Kwave::MP3Encoder::encodeID3Tags(const Kwave::MetaDataList &meta_data,
                     }
                     /* frame->GetField(ID3FN_DESCRIPTION)->Set("..."); */
                     field = frame->GetField(ID3FN_TEXT);
-                    field->SetEncoding(ID3TE_UTF16);
-                    field->Set(static_cast<const unicode_t *>(c.utf16()));
+                    if (field) {
+                        field->SetEncoding(ID3TE_UTF16);
+                        field->Set(static_cast<const unicode_t *>(c.utf16()));
+                    }
 
                     if (tag.AttachFrame(frame)) {
                         frame = nullptr;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.