/* GStreamer
 * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
 *
 * 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

/* FIXME: workaround for SoundTouch.h of version 1.3.1 defining those
 * variables while it shouldn't. */
#undef VERSION
#undef PACKAGE_VERSION
#undef PACKAGE_TARNAME
#undef PACKAGE_STRING
#undef PACKAGE_NAME
#undef PACKAGE_BUGREPORT
#undef PACKAGE

#include <soundtouch/BPMDetect.h>

#include <gst/audio/audio.h>
#include <gst/audio/gstaudiofilter.h>
#include <math.h>
#include <string.h>
#include "gstbpmdetect.hh"

GST_DEBUG_CATEGORY_STATIC (gst_bpm_detect_debug);
#define GST_CAT_DEFAULT gst_bpm_detect_debug

#define GST_BPM_DETECT_GET_PRIVATE(o) (o->priv)

struct _GstBPMDetectPrivate
{
  gfloat bpm;
#ifdef HAVE_SOUNDTOUCH_1_4
    soundtouch::BPMDetect * detect;
#else
  BPMDetect *detect;
#endif
};

/* For soundtouch 1.4 */
#if defined(INTEGER_SAMPLES)
#define SOUNDTOUCH_INTEGER_SAMPLES 1
#elif defined(FLOAT_SAMPLES)
#define SOUNDTOUCH_FLOAT_SAMPLES 1
#endif
 
#if defined(SOUNDTOUCH_FLOAT_SAMPLES)
  #define ALLOWED_CAPS \
    "audio/x-raw, " \
      "format = (string) " GST_AUDIO_NE (F32) ", " \
      "rate = (int) [ 8000, MAX ], " \
      "channels = (int) [ 1, 2 ]"
#elif defined(SOUNDTOUCH_INTEGER_SAMPLES)
  #define ALLOWED_CAPS \
    "audio/x-raw, " \
      "format = (string) " GST_AUDIO_NE (S16) ", " \
      "rate = (int) [ 8000, MAX ], " \
      "channels = (int) [ 1, 2 ]"
#else
#error "Only integer or float samples are supported"
#endif

#define gst_bpm_detect_parent_class parent_class
G_DEFINE_TYPE (GstBPMDetect, gst_bpm_detect, GST_TYPE_AUDIO_FILTER);

static void gst_bpm_detect_finalize (GObject * object);
static gboolean gst_bpm_detect_stop (GstBaseTransform * trans);
static gboolean gst_bpm_detect_event (GstBaseTransform * trans,
    GstEvent * event);
static GstFlowReturn gst_bpm_detect_transform_ip (GstBaseTransform * trans,
    GstBuffer * in);
static gboolean gst_bpm_detect_setup (GstAudioFilter * filter,
    const GstAudioInfo * info);

static void
gst_bpm_detect_class_init (GstBPMDetectClass * klass)
{
  GstCaps *caps;
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GstBaseTransformClass *trans_class = GST_BASE_TRANSFORM_CLASS (klass);
  GstAudioFilterClass *filter_class = GST_AUDIO_FILTER_CLASS (klass);

  GST_DEBUG_CATEGORY_INIT (gst_bpm_detect_debug, "bpm_detect", 0,
      "audio bpm detection element");

  gobject_class->finalize = gst_bpm_detect_finalize;

  gst_element_class_set_static_metadata (element_class, "BPM Detector",
      "Filter/Analyzer/Audio", "Detect the BPM of an audio stream",
      "Sebastian Dröge <slomo@circular-chaos.org>");

  caps = gst_caps_from_string (ALLOWED_CAPS);
  gst_audio_filter_class_add_pad_templates (GST_AUDIO_FILTER_CLASS (klass),
      caps);
  gst_caps_unref (caps);

  trans_class->stop = GST_DEBUG_FUNCPTR (gst_bpm_detect_stop);
  trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_bpm_detect_event);
  trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_bpm_detect_transform_ip);
  trans_class->passthrough_on_same_caps = TRUE;

  filter_class->setup = GST_DEBUG_FUNCPTR (gst_bpm_detect_setup);

  g_type_class_add_private (gobject_class, sizeof (GstBPMDetectPrivate));
}

static void
gst_bpm_detect_init (GstBPMDetect * bpm_detect)
{
  bpm_detect->priv = G_TYPE_INSTANCE_GET_PRIVATE ((bpm_detect),
      GST_TYPE_BPM_DETECT, GstBPMDetectPrivate);

  bpm_detect->priv->detect = NULL;
  bpm_detect->bpm = 0.0;
}

static void
gst_bpm_detect_finalize (GObject * object)
{
  GstBPMDetect *bpm_detect = GST_BPM_DETECT (object);

  if (bpm_detect->priv->detect) {
    delete bpm_detect->priv->detect;

    bpm_detect->priv->detect = NULL;
  }

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static gboolean
gst_bpm_detect_stop (GstBaseTransform * trans)
{
  GstBPMDetect *bpm_detect = GST_BPM_DETECT (trans);

  if (bpm_detect->priv->detect) {
    delete bpm_detect->priv->detect;

    bpm_detect->priv->detect = NULL;
  }
  bpm_detect->bpm = 0.0;

  return TRUE;
}

static gboolean
gst_bpm_detect_event (GstBaseTransform * trans, GstEvent * event)
{
  GstBPMDetect *bpm_detect = GST_BPM_DETECT (trans);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_STOP:
    case GST_EVENT_EOS:
    case GST_EVENT_SEGMENT:
      if (bpm_detect->priv->detect) {
        delete bpm_detect->priv->detect;

        bpm_detect->priv->detect = NULL;
      }
      bpm_detect->bpm = 0.0;
      break;
    default:
      break;
  }

  return TRUE;
}

static gboolean
gst_bpm_detect_setup (GstAudioFilter * filter, const GstAudioInfo * info)
{
  GstBPMDetect *bpm_detect = GST_BPM_DETECT (filter);

  if (bpm_detect->priv->detect) {
    delete bpm_detect->priv->detect;

    bpm_detect->priv->detect = NULL;
  }

  return TRUE;
}

static GstFlowReturn
gst_bpm_detect_transform_ip (GstBaseTransform * trans, GstBuffer * in)
{
  GstBPMDetect *bpm_detect = GST_BPM_DETECT (trans);
  GstAudioFilter *filter = GST_AUDIO_FILTER (trans);
  gint nsamples;
  gfloat bpm;
  GstMapInfo info;

  if (G_UNLIKELY (!bpm_detect->priv->detect)) {
    if (GST_AUDIO_INFO_FORMAT (&filter->info) == GST_AUDIO_FORMAT_UNKNOWN) {
      GST_ERROR_OBJECT (bpm_detect, "No channels or rate set yet");
      return GST_FLOW_ERROR;
    }
#ifdef HAVE_SOUNDTOUCH_1_4
    bpm_detect->priv->detect =
        new soundtouch::BPMDetect (GST_AUDIO_INFO_CHANNELS (&filter->info),
        GST_AUDIO_INFO_RATE (&filter->info));
#else
    bpm_detect->priv->detect =
        new BPMDetect (GST_AUDIO_INFO_CHANNELS (&filter->info),
        GST_AUDIO_INFO_RATE (&filter->info));
#endif
  }

  gst_buffer_map (in, &info, GST_MAP_READ);

  nsamples = info.size / (GST_AUDIO_INFO_BPF (&filter->info) * GST_AUDIO_INFO_CHANNELS (&filter->info));

  /* For stereo BPMDetect->inputSamples() does downmixing into the input
   * data but our buffer data shouldn't be modified.
   */
  if (GST_AUDIO_INFO_CHANNELS (&filter->info) == 1) {
    soundtouch::SAMPLETYPE *inbuf = (soundtouch::SAMPLETYPE *) info.data;

    while (nsamples > 0) {
      bpm_detect->priv->detect->inputSamples (inbuf, MIN (nsamples, 2048));
      nsamples -= 2048;
      inbuf += 2048;
    }
  } else {
    soundtouch::SAMPLETYPE *inbuf, *intmp, data[2 * 2048];

    inbuf = (soundtouch::SAMPLETYPE *) info.data;
    intmp = data;

    while (nsamples > 0) {
      memcpy (intmp, inbuf, sizeof (soundtouch::SAMPLETYPE) * 2 * MIN (nsamples, 2048));
      bpm_detect->priv->detect->inputSamples (intmp, MIN (nsamples, 2048));
      nsamples -= 2048;
      inbuf += 2048 * 2;
    }
  }
  gst_buffer_unmap (in, &info);

  bpm = bpm_detect->priv->detect->getBpm ();
  if (bpm >= 1.0 && fabs (bpm_detect->bpm - bpm) >= 1.0) {
    GstTagList *tags = gst_tag_list_new_empty ();

    gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE_ALL, GST_TAG_BEATS_PER_MINUTE,
        bpm, (void *) NULL);
    gst_pad_push_event (trans->srcpad, gst_event_new_tag (tags));

    GST_INFO_OBJECT (bpm_detect, "Detected BPM: %lf\n", bpm);
    bpm_detect->bpm = bpm;
  }

  return GST_FLOW_OK;
}
