/* GStreamer
 * 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.
 */

/**
 * SECTION:element-cdiocddasrc
 * @see_also: GstCdParanoiaSrc, GstAudioCdSrc
 *
 * <refsect2>
 * <para>
 * cdiocddasrc reads and extracts raw audio from Audio CDs. It can operate
 * in one of two modes:
 * <itemizedlist>
 *  <listitem><para>
 *    treat each track as a separate stream, counting time from the start
 *    of the track to the end of the track and posting EOS at the end of
 *    a track, or
 *  </para></listitem>
 *  <listitem><para>
 *    treat the entire disc as one stream, counting time from the start of
 *    the first track to the end of the last track, posting EOS only at
 *    the end of the last track.
 *  </para></listitem>
 * </itemizedlist>
 * </para>
 * <para>
 * With a recent-enough version of libcdio, the element will extract
 * CD-TEXT if this is supported by the CD-drive and CD-TEXT information
 * is available on the CD. The information will be posted on the bus in
 * form of a tag message.
 * </para>
 * <para>
 * When opened, the element will also calculate a CDDB disc ID and a
 * MusicBrainz disc ID, which applications can use to query online
 * databases for artist/title information. These disc IDs will also be
 * posted on the bus as part of the tag messages.
 * </para>
 * <para>
 * cdiocddasrc supports the GstUriHandler interface, so applications can use
 * playbin with cdda://&lt;track-number&gt; URIs for playback (they will have
 * to connect to playbin's notify::source signal and set the device on the
 * cd source in the notify callback if they want to set the device property).
 * Applications should use seeks in "track" format to switch between different
 * tracks of the same CD (passing a new cdda:// URI to playbin involves opening
 * and closing the CD device, which is much slower).
 * </para>
 * <title>Example launch line</title>
 * <para>
 * <programlisting>
 * gst-launch cdiocddasrc track=5 device=/dev/cdrom ! audioconvert ! vorbisenc ! oggmux ! filesink location=track5.ogg
 * </programlisting>
 * This pipeline extracts track 5 of the audio CD and encodes it into an
 * Ogg/Vorbis file.
 * </para>
 * </refsect2>
 */

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

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

#include <gst/gst.h>
#include "gst/gst-i18n-plugin.h"

#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define SAMPLES_PER_SECTOR (CDIO_CD_FRAMESIZE_RAW / sizeof (gint16))

#define DEFAULT_READ_SPEED   -1

enum
{
  PROP_0 = 0,
  PROP_READ_SPEED
};

G_DEFINE_TYPE (GstCdioCddaSrc, gst_cdio_cdda_src, GST_TYPE_AUDIO_CD_SRC);

static void gst_cdio_cdda_src_finalize (GObject * obj);
static void gst_cdio_cdda_src_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_cdio_cdda_src_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static GstBuffer *gst_cdio_cdda_src_read_sector (GstAudioCdSrc * src,
    gint sector);
static gboolean gst_cdio_cdda_src_open (GstAudioCdSrc * src,
    const gchar * device);
static void gst_cdio_cdda_src_close (GstAudioCdSrc * src);

#if 0
static gchar *
gst_cdio_cdda_src_get_default_device (GstAudioCdSrc * audiocdsrc)
{
  GstCdioCddaSrc *src;
  gchar *default_device, *ret;

  src = GST_CDIO_CDDA_SRC (audiocdsrc);

  /* src->cdio may be NULL here */
  default_device = cdio_get_default_device (src->cdio);

  ret = g_strdup (default_device);
  free (default_device);

  GST_LOG_OBJECT (src, "returning default device: %s", GST_STR_NULL (ret));

  return ret;
}

static gchar **
gst_cdio_cdda_src_probe_devices (GstAudioCdSrc * audiocdsrc)
{
  char **devices, **ret, **d;

  /* FIXME: might return the same hardware device twice, e.g.
   * as /dev/cdrom and /dev/dvd - gotta do something more sophisticated */
  devices = cdio_get_devices (DRIVER_DEVICE);

  if (devices == NULL)
    goto no_devices;

  if (*devices == NULL)
    goto empty_devices;

  ret = g_strdupv (devices);
  for (d = devices; *d != NULL; ++d) {
    GST_DEBUG_OBJECT (audiocdsrc, "device: %s", GST_STR_NULL (*d));
    free (*d);
  }
  free (devices);

  return ret;

  /* ERRORS */
no_devices:
  {
    GST_DEBUG_OBJECT (audiocdsrc, "no devices found");
    return NULL;
  }
empty_devices:
  {
    GST_DEBUG_OBJECT (audiocdsrc, "empty device list found");
    free (devices);
    return NULL;
  }
}
#endif

static GstBuffer *
gst_cdio_cdda_src_read_sector (GstAudioCdSrc * audiocdsrc, gint sector)
{
  GstCdioCddaSrc *src;
  guint8 *data;

  src = GST_CDIO_CDDA_SRC (audiocdsrc);

  data = g_malloc (CDIO_CD_FRAMESIZE_RAW);

  /* can't use pad_alloc because we can't return the GstFlowReturn (FIXME 0.11) */
  if (cdio_read_audio_sector (src->cdio, data, sector) != 0)
    goto read_failed;

  if (src->swap_le_be) {
    gint16 *pcm_data = (gint16 *) data;
    gint i;

    for (i = 0; i < SAMPLES_PER_SECTOR; ++i)
      pcm_data[i] = GUINT16_SWAP_LE_BE (pcm_data[i]);
  }

  return gst_buffer_new_wrapped (data, CDIO_CD_FRAMESIZE_RAW);

  /* ERRORS */
read_failed:
  {
    GST_WARNING_OBJECT (src, "read at sector %d failed!", sector);
    GST_ELEMENT_ERROR (src, RESOURCE, READ,
        (_("Could not read from CD.")),
        ("cdio_read_audio_sector at %d failed: %s", sector,
            g_strerror (errno)));
    g_free (data);
    return NULL;
  }
}

static gboolean
gst_cdio_cdda_src_do_detect_drive_endianness (GstCdioCddaSrc * src, gint from,
    gint to)
{
  gint16 pcm_data[SAMPLES_PER_SECTOR], last_pcm_ne, last_pcm_oe;
  gdouble ne_sumd0, ne_sumd1, ne_factor;
  gdouble oe_sumd0, oe_sumd1, oe_factor;
  gdouble diff;
  gint sector;
  gint i;

  ne_sumd0 = ne_sumd1 = 0.0;
  oe_sumd0 = oe_sumd1 = 0.0;
  last_pcm_ne = 0;
  last_pcm_oe = 0;

  GST_LOG_OBJECT (src, "checking sector %d to %d", from, to);

  for (sector = from; sector < to; ++sector) {
    if (cdio_read_audio_sector (src->cdio, pcm_data, sector) != 0)
      goto read_failed;

    /* only evaluate samples for left channel */
    for (i = 0; i < SAMPLES_PER_SECTOR; i += 2) {
      gint16 pcm;

      /* Native endianness first */
      pcm = pcm_data[i];
      ne_sumd0 += abs (pcm);
      ne_sumd1 += abs (pcm - last_pcm_ne);
      last_pcm_ne = pcm;

      /* other endianness next */
      pcm = GUINT16_SWAP_LE_BE (pcm);
      oe_sumd0 += abs (pcm);
      oe_sumd1 += abs (pcm - last_pcm_oe);
      last_pcm_oe = pcm;
    }

  }

  ne_factor = (ne_sumd1 / ne_sumd0);
  oe_factor = (oe_sumd1 / oe_sumd0);
  diff = ne_factor - oe_factor;

  GST_DEBUG_OBJECT (src, "Native: %.2f, Other: %.2f, diff: %.2f",
      ne_factor, oe_factor, diff);

  if (diff > 0.5) {
    GST_INFO_OBJECT (src, "Drive produces samples in other endianness");
    src->swap_le_be = TRUE;
    return TRUE;
  } else if (diff < -0.5) {
    GST_INFO_OBJECT (src, "Drive produces samples in host endianness");
    src->swap_le_be = FALSE;
    return TRUE;
  } else {
    GST_INFO_OBJECT (src, "Inconclusive, assuming host endianness");
    src->swap_le_be = FALSE;
    return FALSE;
  }

/* ERRORS */
read_failed:
  {
    GST_WARNING_OBJECT (src, "could not read sector %d", sector);
    src->swap_le_be = FALSE;
    return FALSE;
  }
}

static void
gst_cdio_cdda_src_detect_drive_endianness (GstCdioCddaSrc * src, gint first,
    gint last)
{
  gint from, to;

  GST_INFO ("Detecting drive endianness");

  /* try middle of disc first */
  from = (first + last) / 2;
  to = MIN (from + 10, last);
  if (gst_cdio_cdda_src_do_detect_drive_endianness (src, from, to))
    return;

  /* if that was inconclusive, try other places */
  from = (first + last) / 4;
  to = MIN (from + 10, last);
  if (gst_cdio_cdda_src_do_detect_drive_endianness (src, from, to))
    return;

  from = (first + last) * 3 / 4;
  to = MIN (from + 10, last);
  if (gst_cdio_cdda_src_do_detect_drive_endianness (src, from, to))
    return;

  /* if that's still inconclusive, we give up and assume host endianness */
  return;
}

static gboolean
notcdio_track_is_audio_track (const CdIo * p_cdio, track_t i_track)
{
  return (cdio_get_track_format (p_cdio, i_track) == TRACK_FORMAT_AUDIO);
}

static gboolean
gst_cdio_cdda_src_open (GstAudioCdSrc * audiocdsrc, const gchar * device)
{
  GstCdioCddaSrc *src;
  discmode_t discmode;
  gint first_track, num_tracks, i;
  gint first_audio_sector = 0, last_audio_sector = 0;
#if LIBCDIO_VERSION_NUM > 83
  cdtext_t *cdtext;
#endif

  src = GST_CDIO_CDDA_SRC (audiocdsrc);

  g_assert (device != NULL);
  g_assert (src->cdio == NULL);

  GST_LOG_OBJECT (src, "trying to open device %s", device);

  if (!(src->cdio = cdio_open (device, DRIVER_UNKNOWN)))
    goto open_failed;

  discmode = cdio_get_discmode (src->cdio);
  GST_LOG_OBJECT (src, "discmode: %d", (gint) discmode);

  if (discmode != CDIO_DISC_MODE_CD_DA && discmode != CDIO_DISC_MODE_CD_MIXED)
    goto not_audio;

  first_track = cdio_get_first_track_num (src->cdio);
  num_tracks = cdio_get_num_tracks (src->cdio);

  if (num_tracks <= 0 || first_track < 0)
    return TRUE;                /* base class will generate 'has no tracks' error */

  if (src->read_speed != -1)
    cdio_set_speed (src->cdio, src->read_speed);

#if LIBCDIO_VERSION_NUM > 83
  cdtext = cdio_get_cdtext (src->cdio);

  if (NULL == cdtext)
    GST_DEBUG_OBJECT (src, "no CD-TEXT on disc");
  else
    gst_cdio_add_cdtext_album_tags (GST_OBJECT_CAST (src), cdtext,
        audiocdsrc->tags);
#else
  gst_cdio_add_cdtext_album_tags (GST_OBJECT_CAST (src), src->cdio,
      audiocdsrc->tags);
#endif

  GST_LOG_OBJECT (src, "%u tracks, first track: %d", num_tracks, first_track);

  for (i = 0; i < num_tracks; ++i) {
    GstAudioCdSrcTrack track = { 0, };
    gint len_sectors;

    len_sectors = cdio_get_track_sec_count (src->cdio, i + first_track);

    track.num = i + first_track;
    track.is_audio = notcdio_track_is_audio_track (src->cdio, i + first_track);

    /* Note: LSN/LBA confusion all around us; in any case, this does
     * the right thing here (for cddb id calculations etc. as well) */
    track.start = cdio_get_track_lsn (src->cdio, i + first_track);
    track.end = track.start + len_sectors - 1;  /* -1? */

    if (track.is_audio) {
      first_audio_sector = MIN (first_audio_sector, track.start);
      last_audio_sector = MAX (last_audio_sector, track.end);
    }
#if LIBCDIO_VERSION_NUM > 83
    if (NULL != cdtext)
      track.tags = gst_cdio_get_cdtext (GST_OBJECT (src), cdtext,
          i + first_track);
#else
    track.tags = gst_cdio_get_cdtext (GST_OBJECT (src), src->cdio,
        i + first_track);
#endif

    gst_audio_cd_src_add_track (GST_AUDIO_CD_SRC (src), &track);
  }

  /* Try to detect if we need to byte-order swap the samples coming from the
   * drive, which might be the case if the CD drive operates in a different
   * endianness than the host CPU's endianness (happens on e.g. Powerbook G4) */
  gst_cdio_cdda_src_detect_drive_endianness (src, first_audio_sector,
      last_audio_sector);

  return TRUE;

  /* ERRORS */
open_failed:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
        (_("Could not open CD device for reading.")),
        ("cdio_open() failed: %s", g_strerror (errno)));
    return FALSE;
  }
not_audio:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
        (_("Disc is not an Audio CD.")), ("discmode: %d", (gint) discmode));

    cdio_destroy (src->cdio);
    src->cdio = NULL;
    return FALSE;
  }
}

static void
gst_cdio_cdda_src_close (GstAudioCdSrc * audiocdsrc)
{
  GstCdioCddaSrc *src = GST_CDIO_CDDA_SRC (audiocdsrc);

  if (src->cdio) {
    cdio_destroy (src->cdio);
    src->cdio = NULL;
  }
}

static void
gst_cdio_cdda_src_init (GstCdioCddaSrc * src)
{
  src->read_speed = DEFAULT_READ_SPEED; /* don't need atomic access here */
  src->cdio = NULL;
}

static void
gst_cdio_cdda_src_finalize (GObject * obj)
{
  GstCdioCddaSrc *src = GST_CDIO_CDDA_SRC (obj);

  if (src->cdio) {
    cdio_destroy (src->cdio);
    src->cdio = NULL;
  }

  G_OBJECT_CLASS (gst_cdio_cdda_src_parent_class)->finalize (obj);
}

static void
gst_cdio_cdda_src_class_init (GstCdioCddaSrcClass * klass)
{
  GstAudioCdSrcClass *audiocdsrc_class = GST_AUDIO_CD_SRC_CLASS (klass);
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->set_property = gst_cdio_cdda_src_set_property;
  gobject_class->get_property = gst_cdio_cdda_src_get_property;
  gobject_class->finalize = gst_cdio_cdda_src_finalize;

  audiocdsrc_class->open = gst_cdio_cdda_src_open;
  audiocdsrc_class->close = gst_cdio_cdda_src_close;
  audiocdsrc_class->read_sector = gst_cdio_cdda_src_read_sector;
#if 0
  audiocdsrc_class->probe_devices = gst_cdio_cdda_src_probe_devices;
  audiocdsrc_class->get_default_device = gst_cdio_cdda_src_get_default_device;
#endif

  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_READ_SPEED,
      g_param_spec_int ("read-speed", "Read speed",
          "Read from device at the specified speed (-1 = default)", -1, 100,
          DEFAULT_READ_SPEED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  gst_element_class_set_static_metadata (element_class,
      "CD audio source (CDDA)", "Source/File",
      "Read audio from CD using libcdio",
      "Tim-Philipp Müller <tim centricular net>");
}

static void
gst_cdio_cdda_src_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstCdioCddaSrc *src = GST_CDIO_CDDA_SRC (object);

  switch (prop_id) {
    case PROP_READ_SPEED:{
      gint speed;

      speed = g_value_get_int (value);
      g_atomic_int_set (&src->read_speed, speed);
      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_cdio_cdda_src_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstCdioCddaSrc *src = GST_CDIO_CDDA_SRC (object);

  switch (prop_id) {
    case PROP_READ_SPEED:{
      gint speed;

      speed = g_atomic_int_get (&src->read_speed);
      g_value_set_int (value, speed);
      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
