diff Plugins/Input/mpg123/id3_frame_content.c @ 227:539a0fa7f030 trunk

[svn] Unicode support fixes, based on an XMMS patch written by Ilya Konstantinov. <ikonst@users.sourceforge.net>: - Fixes UTF16 to UTF8 down-conversion. - Fixes length management of UTF8 entities. - Doesn't break ASCII support. - Corrects several issues with the original implementation.
author nenolod
date Fri, 25 Nov 2005 20:23:40 -0800
parents fa848bd484d8
children 08973a746a3e
line wrap: on
line diff
--- a/Plugins/Input/mpg123/id3_frame_content.c	Fri Nov 25 19:54:46 2005 -0800
+++ b/Plugins/Input/mpg123/id3_frame_content.c	Fri Nov 25 20:23:40 2005 -0800
@@ -28,6 +28,7 @@
 
 #include <glib.h>
 #include <glib/gi18n.h>
+#include <string.h>
 
 #include "xmms-id3.h"
 
@@ -44,95 +45,95 @@
 char *
 id3_get_content(struct id3_frame *frame)
 {
-    char *text, *text_beg, *ptr;
-    char buffer[256];
-    int spc = sizeof(buffer) - 1;
+     gchar *text, *text_it;
+
+     /* Type check */
+     if (frame->fr_desc->fd_id != ID3_TCON)
+         return NULL;
 
-    /* Type check */
-    if (frame->fr_desc->fd_id != ID3_TCON)
-        return NULL;
+     /* Check if frame is compressed */
+     if (id3_decompress_frame(frame) == -1)
+         return NULL;
+
+     ID3_FRAME_DEFINE_CURSOR(frame);
 
-    /* Check if frame is compressed */
-    if (id3_decompress_frame(frame) == -1)
+     guint8 encoding;
+     ID3_FRAME_READ_OR_RETVAL(encoding, NULL);
+
+     text = text_it = id3_string_decode(encoding, cursor, length);
+
+     if (text == NULL)
         return NULL;
 
-    if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1)
-        text_beg = text = g_strdup((char *) frame->fr_data + 1);
-    else
-        text_beg = text = id3_utf16_to_ascii((char *) frame->fr_data + 1);
+     /*
+      * Expand ID3v1 genre numbers.
+      */
+     while ((text_it = strstr(text_it, "(")) != NULL)
+     {
+         gchar* replace = NULL;
+         gchar* ref_start = text_it + 1;
 
-    /*
-     * If content is just plain text, return it.
-     */
-    if (text[0] != '(') {
-        return text;
-    }
+         if (*ref_start == ')')
+         {
+            /* False alarm */
+            ++text_it;
+            continue;
+         }
+
+         gsize ref_size = strstr(ref_start, ")") - ref_start;
 
-    /*
-     * Expand ID3v1 genre numbers.
-     */
-    ptr = buffer;
-    while (text[0] == '(' && text[1] != '(' && spc > 0) {
-        const char *genre;
-        int num = 0;
-
-        if (text[1] == 'R' && text[2] == 'X') {
-            text += 4;
-            genre = _(" (Remix)");
-            if (ptr == buffer)
-                genre++;
-
-        }
-        else if (text[1] == 'C' && text[2] == 'R') {
-            text += 4;
-            genre = _(" (Cover)");
-            if (ptr == buffer)
-                genre++;
+         if (strncmp(ref_start, "RX", ref_size) == 0)
+         {
+            replace = _("Remix");
+         }
+         else if (strncmp(ref_start, "CR", ref_size) == 0)
+         {
+            replace = _("Cover");
+         }
+         else
+         {
+             /* Maybe an ID3v1 genre? */
+             int genre_number;
+             gchar* genre_number_str = g_strndup(ref_start, ref_size);
+             if (sscanf(genre_number_str, "%d", &genre_number) > 0)
+             {
+                 /* Boundary check */
+                 if (genre_number >= sizeof(mpg123_id3_genres) / sizeof(char *))
+                     continue;
 
-        }
-        else {
-            /* Get ID3v1 genre number */
-            text++;
-            while (*text != ')') {
-                num *= 10;
-                num += *text++ - '0';
-            }
-            text++;
+                 replace = gettext(mpg123_id3_genres[genre_number]);
+             }
+         }
 
-            /* Boundary check */
-            if (num >= sizeof(mpg123_id3_genres) / sizeof(char *))
-                continue;
-
-            genre = gettext(mpg123_id3_genres[num]);
-
-            if (ptr != buffer && spc-- > 0)
-                *ptr++ = '/';
-        }
+         if (replace != NULL)
+         {
+             /* Amazingly hairy code to replace a part of the original genre string
+                with 'replace'. */
+             gchar* copy = g_malloc(strlen(text) - ref_size + strlen(replace) + 1);
+             gsize pos = 0;
+             gsize copy_size;
 
-        /* Expand string into buffer */
-        while (*genre != '\0' && spc > 0) {
-            *ptr++ = *genre++;
-            spc--;
-        }
-    }
+             /* Copy the part before the replaced part */
+             copy_size = ref_start - text;
+             memcpy(copy + pos, text, copy_size);
+             pos += copy_size;
+             /* Copy the replacement instead of the original reference */
+             copy_size = strlen(replace);
+             memcpy(copy + pos, replace, copy_size);
+             pos += copy_size;
+             /* Copy the rest, including the null */
+             memcpy(copy + pos, ref_start + ref_size, strlen(ref_start + ref_size)+1);
 
-    /*
-     * Add plaintext refinement.
-     */
-    if (*text == '(')
-        text++;
-    if (*text != '\0' && ptr != buffer && spc-- > 0)
-        *ptr++ = ' ';
-    while (*text != '\0' && spc > 0) {
-        *ptr++ = *text++;
-        spc--;
-    }
-    *ptr = '\0';
+             /* Put into original variables */
+             gsize offset = text_it - text;
+             g_free(text);
+             text = copy;
+             text_it = text + offset;
+         }
 
-    g_free(text_beg);
+         ++text_it;
+     } 
 
-    /*
-     * Return the expanded content string.
-     */
-    return g_strdup(buffer);
+     return text;
+
 }