gst_plugins_base/gst-libs/gst/tag/tags.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer non-core tag registration and tag utility functions
       
     2  * Copyright (C) 2005 Ross Burton <ross@burtonini.com>
       
     3  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Library General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Library General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Library General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 #ifdef HAVE_CONFIG_H
       
    22 #include "config.h"
       
    23 #endif
       
    24 
       
    25 #ifndef __SYMBIAN32__
       
    26 #include <gst/gst-i18n-plugin.h>
       
    27 #else
       
    28 #include "gst/gst-i18n-plugin.h"
       
    29 #endif
       
    30 #include <gst/gst.h>
       
    31 #include "tag.h"
       
    32 
       
    33 #include <string.h>
       
    34 
       
    35 /**
       
    36  * SECTION:gsttag
       
    37  * @short_description: additional tag definitions for plugins and applications
       
    38  * @see_also: #GstTagList
       
    39  * 
       
    40  * <refsect2>
       
    41  * <para>
       
    42  * Contains additional standardized GStreamer tag definitions for plugins
       
    43  * and applications, and functions to register them with the GStreamer
       
    44  * tag system.
       
    45  * </para>
       
    46  * </refsect2>
       
    47  */
       
    48 
       
    49 
       
    50 static gpointer
       
    51 gst_tag_register_tags_internal (gpointer unused)
       
    52 {
       
    53 #ifdef ENABLE_NLS
       
    54   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       
    55       LOCALEDIR);
       
    56   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
       
    57 #endif
       
    58 
       
    59   /* musicbrainz tags */
       
    60   gst_tag_register (GST_TAG_MUSICBRAINZ_TRACKID, GST_TAG_FLAG_META,
       
    61       G_TYPE_STRING, _("track ID"), _("MusicBrainz track ID"), NULL);
       
    62   gst_tag_register (GST_TAG_MUSICBRAINZ_ARTISTID, GST_TAG_FLAG_META,
       
    63       G_TYPE_STRING, _("artist ID"), _("MusicBrainz artist ID"), NULL);
       
    64   gst_tag_register (GST_TAG_MUSICBRAINZ_ALBUMID, GST_TAG_FLAG_META,
       
    65       G_TYPE_STRING, _("album ID"), _("MusicBrainz album ID"), NULL);
       
    66   gst_tag_register (GST_TAG_MUSICBRAINZ_ALBUMARTISTID, GST_TAG_FLAG_META,
       
    67       G_TYPE_STRING,
       
    68       _("album artist ID"), _("MusicBrainz album artist ID"), NULL);
       
    69   gst_tag_register (GST_TAG_MUSICBRAINZ_TRMID, GST_TAG_FLAG_META,
       
    70       G_TYPE_STRING, _("track TRM ID"), _("MusicBrainz TRM ID"), NULL);
       
    71 
       
    72   /* CDDA tags */
       
    73   gst_tag_register (GST_TAG_CDDA_CDDB_DISCID, GST_TAG_FLAG_META,
       
    74       G_TYPE_STRING, "discid", "CDDB discid for metadata retrieval",
       
    75       gst_tag_merge_use_first);
       
    76 
       
    77   gst_tag_register (GST_TAG_CDDA_CDDB_DISCID_FULL, GST_TAG_FLAG_META,
       
    78       G_TYPE_STRING, "discid full",
       
    79       "CDDB discid for metadata retrieval (full)", gst_tag_merge_use_first);
       
    80 
       
    81   gst_tag_register (GST_TAG_CDDA_MUSICBRAINZ_DISCID, GST_TAG_FLAG_META,
       
    82       G_TYPE_STRING, "musicbrainz-discid",
       
    83       "Musicbrainz discid for metadata retrieval", gst_tag_merge_use_first);
       
    84 
       
    85   gst_tag_register (GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL, GST_TAG_FLAG_META,
       
    86       G_TYPE_STRING, "musicbrainz-discid-full",
       
    87       "Musicbrainz discid for metadata retrieval (full)",
       
    88       gst_tag_merge_use_first);
       
    89 
       
    90   return NULL;
       
    91 }
       
    92 
       
    93 /* FIXME 0.11: rename this to gst_tag_init() or gst_tag_register_tags() */
       
    94 /**
       
    95  * gst_tag_register_musicbrainz_tags
       
    96  *
       
    97  * Registers additional musicbrainz-specific tags with the GStreamer tag
       
    98  * system. Plugins and applications that use these tags should call this
       
    99  * function before using them. Can be called multiple times.
       
   100  */
       
   101 #ifdef __SYMBIAN32__
       
   102 EXPORT_C
       
   103 #endif
       
   104 
       
   105 void
       
   106 gst_tag_register_musicbrainz_tags (void)
       
   107 {
       
   108   static GOnce mb_once = G_ONCE_INIT;
       
   109 
       
   110   g_once (&mb_once, gst_tag_register_tags_internal, NULL);
       
   111 }
       
   112 
       
   113 static void
       
   114 register_tag_image_type_enum (GType * id)
       
   115 {
       
   116   static const GEnumValue image_types[] = {
       
   117     {GST_TAG_IMAGE_TYPE_UNDEFINED, "GST_TAG_IMAGE_TYPE_UNDEFINED", "undefined"},
       
   118     {GST_TAG_IMAGE_TYPE_FRONT_COVER, "GST_TAG_IMAGE_TYPE_FRONT_COVER",
       
   119         "front-cover"},
       
   120     {GST_TAG_IMAGE_TYPE_BACK_COVER, "GST_TAG_IMAGE_TYPE_BACK_COVER",
       
   121         "back-cover"},
       
   122     {GST_TAG_IMAGE_TYPE_LEAFLET_PAGE, "GST_TAG_IMAGE_TYPE_LEAFLET_PAGE",
       
   123         "leaflet-page"},
       
   124     {GST_TAG_IMAGE_TYPE_MEDIUM, "GST_TAG_IMAGE_TYPE_MEDIUM", "medium"},
       
   125     {GST_TAG_IMAGE_TYPE_LEAD_ARTIST, "GST_TAG_IMAGE_TYPE_LEAD_ARTIST",
       
   126         "lead-artist"},
       
   127     {GST_TAG_IMAGE_TYPE_ARTIST, "GST_TAG_IMAGE_TYPE_ARTIST", "artist"},
       
   128     {GST_TAG_IMAGE_TYPE_CONDUCTOR, "GST_TAG_IMAGE_TYPE_CONDUCTOR", "conductor"},
       
   129     {GST_TAG_IMAGE_TYPE_BAND_ORCHESTRA, "GST_TAG_IMAGE_TYPE_BAND_ORCHESTRA",
       
   130         "band-orchestra"},
       
   131     {GST_TAG_IMAGE_TYPE_COMPOSER, "GST_TAG_IMAGE_TYPE_COMPOSER", "composer"},
       
   132     {GST_TAG_IMAGE_TYPE_LYRICIST, "GST_TAG_IMAGE_TYPE_LYRICIST", "lyricist"},
       
   133     {GST_TAG_IMAGE_TYPE_RECORDING_LOCATION,
       
   134           "GST_TAG_IMAGE_TYPE_RECORDING_LOCATION",
       
   135         "recording-location"},
       
   136     {GST_TAG_IMAGE_TYPE_DURING_RECORDING, "GST_TAG_IMAGE_TYPE_DURING_RECORDING",
       
   137         "during-recording"},
       
   138     {GST_TAG_IMAGE_TYPE_DURING_PERFORMANCE,
       
   139           "GST_TAG_IMAGE_TYPE_DURING_PERFORMANCE",
       
   140         "during-performance"},
       
   141     {GST_TAG_IMAGE_TYPE_VIDEO_CAPTURE, "GST_TAG_IMAGE_TYPE_VIDEO_CAPTURE",
       
   142         "video-capture"},
       
   143     {GST_TAG_IMAGE_TYPE_FISH, "GST_TAG_IMAGE_TYPE_FISH", "fish"},
       
   144     {GST_TAG_IMAGE_TYPE_ILLUSTRATION, "GST_TAG_IMAGE_TYPE_ILLUSTRATION",
       
   145         "illustration"},
       
   146     {GST_TAG_IMAGE_TYPE_BAND_ARTIST_LOGO, "GST_TAG_IMAGE_TYPE_BAND_ARTIST_LOGO",
       
   147         "artist-logo"},
       
   148     {GST_TAG_IMAGE_TYPE_PUBLISHER_STUDIO_LOGO,
       
   149           "GST_TAG_IMAGE_TYPE_PUBLISHER_STUDIO_LOGO",
       
   150         "publisher-studio-logo"},
       
   151     {0, NULL, NULL}
       
   152   };
       
   153 
       
   154   *id = g_enum_register_static ("GstTagImageType", image_types);
       
   155 }
       
   156 #ifdef __SYMBIAN32__
       
   157 EXPORT_C
       
   158 #endif
       
   159 
       
   160 
       
   161 GType
       
   162 gst_tag_image_type_get_type (void)
       
   163 {
       
   164   static GType id;
       
   165   static GOnce once = G_ONCE_INIT;
       
   166 
       
   167   g_once (&once, (GThreadFunc) register_tag_image_type_enum, &id);
       
   168   return id;
       
   169 }
       
   170 
       
   171 /**
       
   172  * gst_tag_parse_extended_comment:
       
   173  * @ext_comment: an extended comment string, see #GST_TAG_EXTENDED_COMMENT
       
   174  * @key: return location for the comment description key, or NULL
       
   175  * @lang: return location for the comment ISO-639 language code, or NULL
       
   176  * @value: return location for the actual comment string, or NULL
       
   177  * @fail_if_no_key: whether to fail if strings are not in key=value form
       
   178  *
       
   179  * Convenience function to parse a GST_TAG_EXTENDED_COMMENT string and
       
   180  * separate it into its components.
       
   181  *
       
   182  * If successful, @key, @lang and/or @value will be set to newly allocated
       
   183  * strings that you need to free with g_free() when done. @key and @lang
       
   184  * may also be set to NULL by this function if there is no key or no language
       
   185  * code in the extended comment string.
       
   186  *
       
   187  * Returns: TRUE if the string could be parsed, otherwise FALSE
       
   188  *
       
   189  * Since: 0.10.10
       
   190  */
       
   191 #ifdef __SYMBIAN32__
       
   192 EXPORT_C
       
   193 #endif
       
   194 
       
   195 gboolean
       
   196 gst_tag_parse_extended_comment (const gchar * ext_comment, gchar ** key,
       
   197     gchar ** lang, gchar ** value, gboolean fail_if_no_key)
       
   198 {
       
   199   const gchar *div, *bop, *bcl;
       
   200 
       
   201   g_return_val_if_fail (ext_comment != NULL, FALSE);
       
   202   g_return_val_if_fail (g_utf8_validate (ext_comment, -1, NULL), FALSE);
       
   203 
       
   204   if (key)
       
   205     *key = NULL;
       
   206   if (lang)
       
   207     *lang = NULL;
       
   208 
       
   209   div = strchr (ext_comment, '=');
       
   210   bop = strchr (ext_comment, '[');
       
   211   bcl = strchr (ext_comment, ']');
       
   212 
       
   213   if (div == NULL) {
       
   214     if (fail_if_no_key)
       
   215       return FALSE;
       
   216     if (value)
       
   217       *value = g_strdup (ext_comment);
       
   218     return TRUE;
       
   219   }
       
   220 
       
   221   if (bop != NULL && bop < div) {
       
   222     if (bcl < bop || bcl > div)
       
   223       return FALSE;
       
   224     if (key)
       
   225       *key = g_strndup (ext_comment, bop - ext_comment);
       
   226     if (lang)
       
   227       *lang = g_strndup (bop + 1, bcl - bop - 1);
       
   228   } else {
       
   229     if (key)
       
   230       *key = g_strndup (ext_comment, div - ext_comment);
       
   231   }
       
   232 
       
   233   if (value)
       
   234     *value = g_strdup (div + 1);
       
   235 
       
   236   return TRUE;
       
   237 }
       
   238 
       
   239 /**
       
   240  * gst_tag_freeform_string_to_utf8:
       
   241  * @data: string data
       
   242  * @size: length of string data, or -1 if the string is NUL-terminated
       
   243  * @env_vars: a NULL-terminated string array of environment variable names,
       
   244  *            or NULL
       
   245  *
       
   246  * Convenience function to read a string with unknown character encoding. If
       
   247  * the string is already in UTF-8 encoding, it will be returned right away.
       
   248  * Otherwise, the environment will be searched for a number of environment
       
   249  * variables (whose names are specified in the NULL-terminated string array
       
   250  * @env_vars) containing a list of character encodings to try/use. If none
       
   251  * are specified, the current locale will be tried. If that also doesn't work,
       
   252  * ISO-8859-1 is assumed (which will almost always succeed).
       
   253  *
       
   254  * Returns: a newly-allocated string in UTF-8 encoding, or NULL
       
   255  *
       
   256  * Since: 0.10.13
       
   257  */
       
   258 #ifdef __SYMBIAN32__
       
   259 EXPORT_C
       
   260 #endif
       
   261 
       
   262 gchar *
       
   263 gst_tag_freeform_string_to_utf8 (const gchar * data, gint size,
       
   264     const gchar ** env_vars)
       
   265 {
       
   266   const gchar *cur_loc = NULL;
       
   267   gsize bytes_read;
       
   268   gchar *utf8 = NULL;
       
   269 
       
   270   g_return_val_if_fail (data != NULL, NULL);
       
   271 
       
   272   if (size < 0)
       
   273     size = strlen (data);
       
   274 
       
   275   /* chop off trailing string terminators to make sure utf8_validate doesn't
       
   276    * get to see them (since that would make the utf8 check fail) */
       
   277   while (size > 0 && data[size - 1] == '\0')
       
   278     --size;
       
   279 
       
   280   /* Should we try the charsets specified
       
   281    * via environment variables FIRST ? */
       
   282   if (g_utf8_validate (data, size, NULL)) {
       
   283     utf8 = g_strndup (data, size);
       
   284     GST_LOG ("String '%s' is valid UTF-8 already", utf8);
       
   285     goto beach;
       
   286   }
       
   287 
       
   288   while (env_vars && *env_vars != NULL) {
       
   289     const gchar *env = NULL;
       
   290 
       
   291     /* Try charsets specified via the environment */
       
   292     env = g_getenv (*env_vars);
       
   293     if (env != NULL && *env != '\0') {
       
   294       gchar **c, **csets;
       
   295 
       
   296       csets = g_strsplit (env, G_SEARCHPATH_SEPARATOR_S, -1);
       
   297 
       
   298       for (c = csets; c && *c; ++c) {
       
   299         GST_LOG ("Trying to convert freeform string to UTF-8 from '%s'", *c);
       
   300         if ((utf8 =
       
   301                 g_convert (data, size, "UTF-8", *c, &bytes_read, NULL, NULL))) {
       
   302           if (bytes_read == size) {
       
   303             g_strfreev (csets);
       
   304             goto beach;
       
   305           }
       
   306           g_free (utf8);
       
   307           utf8 = NULL;
       
   308         }
       
   309       }
       
   310 
       
   311       g_strfreev (csets);
       
   312     }
       
   313     ++env_vars;
       
   314   }
       
   315 
       
   316   /* Try current locale (if not UTF-8) */
       
   317   if (!g_get_charset (&cur_loc)) {
       
   318     GST_LOG ("Trying to convert freeform string using locale ('%s')", cur_loc);
       
   319     if ((utf8 = g_locale_to_utf8 (data, size, &bytes_read, NULL, NULL))) {
       
   320       if (bytes_read == size) {
       
   321         goto beach;
       
   322       }
       
   323       g_free (utf8);
       
   324       utf8 = NULL;
       
   325     }
       
   326   }
       
   327 
       
   328   /* Try ISO-8859-1 */
       
   329   GST_LOG ("Trying to convert freeform string using ISO-8859-1 fallback");
       
   330   utf8 = g_convert (data, size, "UTF-8", "ISO-8859-1", &bytes_read, NULL, NULL);
       
   331   if (utf8 != NULL && bytes_read == size) {
       
   332     goto beach;
       
   333   }
       
   334 
       
   335   g_free (utf8);
       
   336   return NULL;
       
   337 
       
   338 beach:
       
   339 
       
   340   g_strchomp (utf8);
       
   341   if (utf8 && utf8[0] != '\0') {
       
   342     GST_LOG ("Returning '%s'", utf8);
       
   343     return utf8;
       
   344   }
       
   345 
       
   346   g_free (utf8);
       
   347   return NULL;
       
   348 }