/* GStreamer
 * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
 * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
 *
 * 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., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gst/gst.h>
#include <gst/tag/tag.h>

static gboolean plugin_init (GstPlugin * plugin);

/* cdio headers redefine VERSION etc., so do this here before including them */
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    cdio,
    "Read audio from audio CDs",
    plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);

#include "gstcdio.h"
#include "gstcdiocddasrc.h"

#include <cdio/logging.h>

GST_DEBUG_CATEGORY (gst_cdio_debug);

void
gst_cdio_add_cdtext_field (GstObject * src, cdtext_t * cdtext, track_t track,
    cdtext_field_t field, const gchar * gst_tag, GstTagList ** p_tags)
{
  const gchar *vars[] = { "GST_CDTEXT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
  const gchar *txt;
  gchar *txt_utf8;

#if LIBCDIO_VERSION_NUM > 83 || LIBCDIO_VERSION_NUM < 76
  txt = cdtext_get_const (cdtext, field, track);
#else
  txt = cdtext_get_const (field, cdtext);
#endif
  if (txt == NULL || *txt == '\0') {
    GST_DEBUG_OBJECT (src, "empty CD-TEXT field %u (%s)", field, gst_tag);
    return;
  }

  /* The character encoding is not specified, and there is no provision
   * for indicating in the CD-Text data which encoding is in use.. */
  txt_utf8 = gst_tag_freeform_string_to_utf8 (txt, -1, vars);

  if (txt_utf8 == NULL) {
    GST_WARNING_OBJECT (src, "CD-TEXT %s could not be converted to UTF-8, "
        "try setting the GST_CDTEXT_TAG_ENCODING or GST_TAG_ENCODING "
        "environment variable", gst_tag);
    return;
  }

  /* FIXME: beautify strings (they might be all uppercase for example)? */

  if (*p_tags == NULL)
    *p_tags = gst_tag_list_new_empty ();

  gst_tag_list_add (*p_tags, GST_TAG_MERGE_REPLACE, gst_tag, txt_utf8, NULL);

  GST_DEBUG_OBJECT (src, "CD-TEXT: %s = %s", gst_tag, txt_utf8);
  g_free (txt_utf8);
}

GstTagList *
#if LIBCDIO_VERSION_NUM > 83 || LIBCDIO_VERSION_NUM < 76
gst_cdio_get_cdtext (GstObject * src, cdtext_t * t, track_t track)
{
  GstTagList *tags = NULL;

#else
gst_cdio_get_cdtext (GstObject * src, CdIo * cdio, track_t track)
{
  GstTagList *tags = NULL;
  cdtext_t *t;

  t = cdio_get_cdtext (cdio, track);
  if (t == NULL) {
    GST_DEBUG_OBJECT (src, "no CD-TEXT for track %u", track);
    return NULL;
  }
#endif

  gst_cdio_add_cdtext_field (src, t, track, CDTEXT_FIELD_PERFORMER,
      GST_TAG_ARTIST, &tags);
  gst_cdio_add_cdtext_field (src, t, track, CDTEXT_FIELD_TITLE, GST_TAG_TITLE,
      &tags);

  return tags;
}

void
#if LIBCDIO_VERSION_NUM > 83 || LIBCDIO_VERSION_NUM < 76
gst_cdio_add_cdtext_album_tags (GstObject * src, cdtext_t * t,
    GstTagList * tags)
{
#else
gst_cdio_add_cdtext_album_tags (GstObject * src, CdIo * cdio, GstTagList * tags)
{
  cdtext_t *t;

  t = cdio_get_cdtext (cdio, 0);
  if (t == NULL) {
    GST_DEBUG_OBJECT (src, "no CD-TEXT for album");
    return;
  }
#endif

  gst_cdio_add_cdtext_field (src, t, 0, CDTEXT_FIELD_PERFORMER,
      GST_TAG_ALBUM_ARTIST, &tags);
  gst_cdio_add_cdtext_field (src, t, 0, CDTEXT_FIELD_TITLE, GST_TAG_ALBUM,
      &tags);
  gst_cdio_add_cdtext_field (src, t, 0, CDTEXT_FIELD_GENRE, GST_TAG_GENRE,
      &tags);
  GST_DEBUG ("CD-TEXT album tags: %" GST_PTR_FORMAT, tags);
}

static void
gst_cdio_log_handler (cdio_log_level_t level, const char *msg)
{
  const gchar *level_str[] = { "DEBUG", "INFO", "WARN", "ERROR", "ASSERT" };
  const gchar *s;

  s = level_str[CLAMP (level, 1, G_N_ELEMENTS (level_str)) - 1];
  GST_DEBUG ("CDIO-%s: %s", s, GST_STR_NULL (msg));
}

static gboolean
plugin_init (GstPlugin * plugin)
{
  if (!gst_element_register (plugin, "cdiocddasrc", GST_RANK_SECONDARY - 1,
          GST_TYPE_CDIO_CDDA_SRC))
    return FALSE;

  cdio_log_set_handler (gst_cdio_log_handler);

  GST_DEBUG_CATEGORY_INIT (gst_cdio_debug, "cdio", 0, "libcdio elements");

  return TRUE;
}
