Index: tag.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst-libs/gst/tag/tag.h,v
retrieving revision 1.13
diff -u -p -r1.13 tag.h
--- tag.h	23 Sep 2006 13:21:07 -0000	1.13
+++ tag.h	6 Feb 2007 18:16:43 -0000
@@ -210,8 +210,12 @@ gboolean                gst_tag_parse_ex
                                                         gchar       ** value,
                                                         gboolean       fail_if_no_key);
 
+gchar                 * gst_tag_freeform_string_to_utf8 (const gchar  * data,
+                                                         gint           size,
+                                                         const gchar ** env_vars);
+
 /* FIXME 0.11: replace with a more general gst_tag_library_init() */
-void gst_tag_register_musicbrainz_tags (void);
+void                    gst_tag_register_musicbrainz_tags (void);
 
 G_END_DECLS
 
Index: tags.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst-libs/gst/tag/tags.c,v
retrieving revision 1.7
diff -u -p -r1.7 tags.c
--- tags.c	23 Sep 2006 13:21:07 -0000	1.7
+++ tags.c	6 Feb 2007 18:16:43 -0000
@@ -222,3 +222,97 @@ gst_tag_parse_extended_comment (const gc
 
   return TRUE;
 }
+
+/**
+ * gst_tag_freeform_string_to_utf8:
+ * @data: string data
+ * @size: length of string data, or -1 if the string is NUL-terminated
+ * @env_vars: a NULL-terminated string array of environment variable names,
+ *            or NULL
+ *
+ * Convenience function to read a string with unknown character encoding. If
+ * the string is already in UTF-8 encoding, it will be returned right away.
+ * Otherwise, the environment will be searched for a number of environment
+ * variables (whose names are specified in the NULL-terminated string array
+ * @env_vars) containing a list of character encodings to try/use. If none
+ * are specified, the current locale will be tried. If that also doesn't work,
+ * ISO-8859-1 is assumed (which will almost always succeed).
+ *
+ * Returns: a newly-allocated string in UTF-8 encoding, or NULL
+ *
+ * Since: 0.10.12
+ */
+gchar *
+gst_tag_freeform_string_to_utf8 (const gchar * data, gint size,
+    const gchar ** env_vars)
+{
+  const gchar *env = NULL;
+  gsize bytes_read;
+  gchar *utf8 = NULL;
+
+  g_return_val_if_fail (data != NULL, NULL);
+
+  if (size < 0)
+    size = strlen (data);
+
+  /* Should we try the charsets specified
+   * via environment variables FIRST ? */
+  if (g_utf8_validate (data, size, NULL))
+    return g_strndup (data, size);
+
+  while ((env == NULL || *env == '\0') && env_vars && *env_vars != NULL) {
+    env = g_getenv (*env_vars);
+    ++env_vars;
+  }
+
+  /* Try charsets specified via the environment */
+  if (env != NULL && *env != '\0') {
+    gchar **c, **csets;
+
+    csets = g_strsplit (env, G_SEARCHPATH_SEPARATOR_S, -1);
+
+    for (c = csets; c && *c; ++c) {
+      if ((utf8 =
+              g_convert (data, size, "UTF-8", *c, &bytes_read, NULL, NULL))) {
+        if (bytes_read == size) {
+          g_strfreev (csets);
+          goto beach;
+        }
+        g_free (utf8);
+        utf8 = NULL;
+      }
+    }
+
+    g_strfreev (csets);
+  }
+
+  /* Try current locale (if not UTF-8) */
+  if (!g_get_charset (&env)) {
+    if ((utf8 = g_locale_to_utf8 (data, size, &bytes_read, NULL, NULL))) {
+      if (bytes_read == size) {
+        goto beach;
+      }
+      g_free (utf8);
+      utf8 = NULL;
+    }
+  }
+
+  /* Try ISO-8859-1 */
+  utf8 =
+      g_convert (data, size, "UTF-8", "ISO-8859-1", &bytes_read, NULL, NULL);
+  if (utf8 != NULL && bytes_read == size) {
+    goto beach;
+  }
+
+  g_free (utf8);
+  return NULL;
+
+beach:
+
+  g_strchomp (utf8);
+  if (utf8 && utf8[0] != '\0')
+    return utf8;
+
+  g_free (utf8);
+  return NULL;
+}
