/* GStreamer audio filter base class
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
 * Copyright (C) <2003> David Schleef <ds@schleef.org>
 * Copyright (C) <2007> 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:gstaudiofilter
 * @title: GstAudioFilter
 * @short_description: Base class for simple audio filters
 *
 * #GstAudioFilter is a #GstBaseTransform<!-- -->-derived base class for simple audio
 * filters, ie. those that output the same format that they get as input.
 *
 * #GstAudioFilter will parse the input format for you (with error checking)
 * before calling your setup function. Also, elements deriving from
 * #GstAudioFilter may use gst_audio_filter_class_add_pad_templates() from
 * their class_init function to easily configure the set of caps/formats that
 * the element is able to handle.
 *
 * Derived classes should override the #GstAudioFilterClass.setup() and
 * #GstBaseTransformClass.transform_ip() and/or
 * #GstBaseTransformClass.transform()
 * virtual functions in their class_init function.
 */

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

#include "gstaudiofilter.h"

#include <string.h>

GST_DEBUG_CATEGORY_STATIC (audiofilter_dbg);
#define GST_CAT_DEFAULT audiofilter_dbg

static GstStateChangeReturn gst_audio_filter_change_state (GstElement * element,
    GstStateChange transition);
static gboolean gst_audio_filter_set_caps (GstBaseTransform * btrans,
    GstCaps * incaps, GstCaps * outcaps);
static gboolean gst_audio_filter_get_unit_size (GstBaseTransform * btrans,
    GstCaps * caps, gsize * size);
static GstFlowReturn gst_audio_filter_submit_input_buffer (GstBaseTransform *
    btrans, gboolean is_discont, GstBuffer * input);

#define do_init G_STMT_START { \
    GST_DEBUG_CATEGORY_INIT (audiofilter_dbg, "audiofilter", 0, "audiofilter"); \
} G_STMT_END

G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstAudioFilter, gst_audio_filter,
    GST_TYPE_BASE_TRANSFORM, do_init);

static gboolean
gst_audio_filter_transform_meta (GstBaseTransform * trans, GstBuffer * inbuf,
    GstMeta * meta, GstBuffer * outbuf)
{
  const GstMetaInfo *info = meta->info;
  const gchar *const *tags;

  tags = gst_meta_api_type_get_tags (info->api);

  if (!tags || (g_strv_length ((gchar **) tags) == 1
          && gst_meta_api_type_has_tag (info->api,
              g_quark_from_string (GST_META_TAG_AUDIO_STR))))
    return TRUE;

  return
      GST_BASE_TRANSFORM_CLASS (gst_audio_filter_parent_class)->transform_meta
      (trans, inbuf, meta, outbuf);
}

static void
gst_audio_filter_class_init (GstAudioFilterClass * klass)
{
  GstBaseTransformClass *basetrans_class = (GstBaseTransformClass *) klass;
  GstElementClass *gstelement_class = (GstElementClass *) klass;

  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_audio_filter_change_state);
  basetrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_filter_set_caps);
  basetrans_class->get_unit_size =
      GST_DEBUG_FUNCPTR (gst_audio_filter_get_unit_size);
  basetrans_class->transform_meta = gst_audio_filter_transform_meta;
  basetrans_class->submit_input_buffer = gst_audio_filter_submit_input_buffer;
}

static void
gst_audio_filter_init (GstAudioFilter * self)
{
  gst_audio_info_init (&self->info);
}

/* we override the state change vfunc here instead of GstBaseTransform's stop
 * vfunc, so GstAudioFilter-derived elements can override ::stop() for their
 * own purposes without having to worry about chaining up */
static GstStateChangeReturn
gst_audio_filter_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstAudioFilter *filter = GST_AUDIO_FILTER (element);

  ret =
      GST_ELEMENT_CLASS (gst_audio_filter_parent_class)->change_state (element,
      transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
    case GST_STATE_CHANGE_READY_TO_NULL:
      gst_audio_info_init (&filter->info);
      break;
    default:
      break;
  }

  return ret;
}

static gboolean
gst_audio_filter_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
    GstCaps * outcaps)
{
  GstAudioFilterClass *klass;
  GstAudioFilter *filter = GST_AUDIO_FILTER (btrans);
  GstAudioInfo info;
  gboolean ret = TRUE;

  GST_LOG_OBJECT (filter, "caps: %" GST_PTR_FORMAT, incaps);
  GST_LOG_OBJECT (filter, "info: %d", GST_AUDIO_FILTER_RATE (filter));

  if (!gst_audio_info_from_caps (&info, incaps))
    goto invalid_format;

  klass = GST_AUDIO_FILTER_GET_CLASS (filter);

  if (klass->setup)
    ret = klass->setup (filter, &info);

  if (ret) {
    filter->info = info;
    GST_LOG_OBJECT (filter, "configured caps: %" GST_PTR_FORMAT, incaps);
  }

  return ret;

  /* ERROR */
invalid_format:
  {
    GST_WARNING_OBJECT (filter, "couldn't parse %" GST_PTR_FORMAT, incaps);
    return FALSE;
  }
}

static GstFlowReturn
gst_audio_filter_submit_input_buffer (GstBaseTransform * btrans,
    gboolean is_discont, GstBuffer * input)
{
  GstAudioFilter *filter = GST_AUDIO_FILTER (btrans);

  if (btrans->segment.format == GST_FORMAT_TIME) {
    input =
        gst_audio_buffer_clip (input, &btrans->segment, filter->info.rate,
        filter->info.bpf);

    if (!input)
      return GST_FLOW_OK;
  }

  return
      GST_BASE_TRANSFORM_CLASS
      (gst_audio_filter_parent_class)->submit_input_buffer (btrans, is_discont,
      input);
}

static gboolean
gst_audio_filter_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
    gsize * size)
{
  GstAudioInfo info;

  if (!gst_audio_info_from_caps (&info, caps))
    return FALSE;

  *size = GST_AUDIO_INFO_BPF (&info);

  return TRUE;
}

/**
 * gst_audio_filter_class_add_pad_templates:
 * @klass: an #GstAudioFilterClass
 * @allowed_caps: what formats the filter can handle, as #GstCaps
 *
 * Convenience function to add pad templates to this element class, with
 * @allowed_caps as the caps that can be handled.
 *
 * This function is usually used from within a GObject class_init function.
 */
void
gst_audio_filter_class_add_pad_templates (GstAudioFilterClass * klass,
    GstCaps * allowed_caps)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GstPadTemplate *pad_template;

  g_return_if_fail (GST_IS_AUDIO_FILTER_CLASS (klass));
  g_return_if_fail (GST_IS_CAPS (allowed_caps));

  pad_template = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
      allowed_caps);
  gst_element_class_add_pad_template (element_class, pad_template);

  pad_template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
      allowed_caps);
  gst_element_class_add_pad_template (element_class, pad_template);
}
