/* GStreamer
 *
 * Copyright (C) 2011 Stefan Sauer <ensonic@users.sf.net>
 *
 * gstcontrolbinding.c: Attachment for control sources
 *
 * 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:gstcontrolbinding
 * @title: GstControlBinding
 * @short_description: attachment for control source sources
 *
 * A base class for value mapping objects that attaches control sources to gobject
 * properties. Such an object is taking one or more #GstControlSource instances,
 * combines them and maps the resulting value to the type and value range of the
 * bound property.
 */
/* FIXME(ensonic): should we make gst_object_add_control_binding() internal
 * - we create the control_binding for a certain object anyway
 * - we could call gst_object_add_control_binding() at the end of
 *   gst_control_binding_constructor()
 * - the weak-ref on object is not nice, as is the same as gst_object_parent()
 *   once the object is added to the parent
 *
 * - another option would be to defer what is done in _constructor to when
 *   the parent is set (need to listen to the signal then)
 *   then basically I could
 *   a) remove the obj arg and wait the binding to be added or
 *   b) add the binding from constructor, unref object there and make obj
 *      writeonly
 */

#include "gst_private.h"

#include <glib-object.h>
#include <gst/gst.h>

#include "gstcontrolbinding.h"

#include <math.h>

#define GST_CAT_DEFAULT control_binding_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);

#define _do_init \
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontrolbinding", 0, \
      "dynamic parameter control source attachment");

static GObject *gst_control_binding_constructor (GType type,
    guint n_construct_params, GObjectConstructParam * construct_params);
static void gst_control_binding_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_control_binding_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_control_binding_dispose (GObject * object);
static void gst_control_binding_finalize (GObject * object);

G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstControlBinding, gst_control_binding,
    GST_TYPE_OBJECT, _do_init);

struct _GstControlBindingPrivate
{
  GWeakRef object;
};

enum
{
  PROP_0,
  PROP_OBJECT,
  PROP_NAME,
  PROP_LAST
};

static GParamSpec *properties[PROP_LAST];

static void
gst_control_binding_class_init (GstControlBindingClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  g_type_class_add_private (klass, sizeof (GstControlBindingPrivate));

  gobject_class->constructor = gst_control_binding_constructor;
  gobject_class->set_property = gst_control_binding_set_property;
  gobject_class->get_property = gst_control_binding_get_property;
  gobject_class->dispose = gst_control_binding_dispose;
  gobject_class->finalize = gst_control_binding_finalize;

  properties[PROP_OBJECT] =
      g_param_spec_object ("object", "Object",
      "The object of the property", GST_TYPE_OBJECT,
      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);

  properties[PROP_NAME] =
      g_param_spec_string ("name", "Name", "The name of the property", NULL,
      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);


  g_object_class_install_properties (gobject_class, PROP_LAST, properties);
}

static void
gst_control_binding_init (GstControlBinding * binding)
{
  binding->ABI.abi.priv =
      G_TYPE_INSTANCE_GET_PRIVATE (binding, GST_TYPE_CONTROL_BINDING,
      GstControlBindingPrivate);
  g_weak_ref_init (&binding->ABI.abi.priv->object, NULL);
}

static GObject *
gst_control_binding_constructor (GType type, guint n_construct_params,
    GObjectConstructParam * construct_params)
{
  GstControlBinding *binding;
  GParamSpec *pspec;
  GstObject *object;

  binding =
      GST_CONTROL_BINDING (G_OBJECT_CLASS (gst_control_binding_parent_class)
      ->constructor (type, n_construct_params, construct_params));

  object = g_weak_ref_get (&binding->ABI.abi.priv->object);
  if (!object) {
    GST_WARNING_OBJECT (object, "no object set");
    return (GObject *) binding;
  }

  GST_INFO_OBJECT (object, "trying to put property '%s' under control",
      binding->name);

  /* check if the object has a property of that name */
  if ((pspec =
          g_object_class_find_property (G_OBJECT_GET_CLASS (object),
              binding->name))) {
    GST_DEBUG_OBJECT (object, "  psec->flags : 0x%08x", pspec->flags);

    /* check if this param is witable && controlable && !construct-only */
    if ((pspec->flags & (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE |
                G_PARAM_CONSTRUCT_ONLY)) ==
        (G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE)) {
      binding->pspec = pspec;
    } else {
      GST_WARNING_OBJECT (object,
          "property '%s' on class '%s' needs to "
          "be writeable, controlable and not construct_only", binding->name,
          G_OBJECT_TYPE_NAME (object));
    }
  } else {
    GST_WARNING_OBJECT (object, "class '%s' has no property '%s'",
        G_OBJECT_TYPE_NAME (object), binding->name);
  }

  gst_object_unref (object);

  return (GObject *) binding;
}

static void
gst_control_binding_dispose (GObject * object)
{
  GstControlBinding *self = GST_CONTROL_BINDING (object);

  /* we did not took a reference */
  g_object_remove_weak_pointer ((GObject *) self->__object,
      (gpointer *) & self->__object);
  self->__object = NULL;
  g_weak_ref_clear (&self->ABI.abi.priv->object);

  ((GObjectClass *) gst_control_binding_parent_class)->dispose (object);
}

static void
gst_control_binding_finalize (GObject * object)
{
  GstControlBinding *self = GST_CONTROL_BINDING (object);

  g_free (self->name);

  ((GObjectClass *) gst_control_binding_parent_class)->finalize (object);
}

static void
gst_control_binding_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstControlBinding *self = GST_CONTROL_BINDING (object);

  switch (prop_id) {
    case PROP_OBJECT:
      /* do not ref to avoid a ref cycle */
      self->__object = g_value_get_object (value);
      g_object_add_weak_pointer ((GObject *) self->__object,
          (gpointer *) & self->__object);

      g_weak_ref_set (&self->ABI.abi.priv->object, self->__object);
      break;
    case PROP_NAME:
      self->name = g_value_dup_string (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_control_binding_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstControlBinding *self = GST_CONTROL_BINDING (object);

  switch (prop_id) {
    case PROP_OBJECT:
      g_value_take_object (value, g_weak_ref_get (&self->ABI.abi.priv->object));
      break;
    case PROP_NAME:
      g_value_set_string (value, self->name);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

/* functions */

/**
 * gst_control_binding_sync_values:
 * @binding: the control binding
 * @object: the object that has controlled properties
 * @timestamp: the time that should be processed
 * @last_sync: the last time this was called
 *
 * Sets the property of the @object, according to the #GstControlSources that
 * handle them and for the given timestamp.
 *
 * If this function fails, it is most likely the application developers fault.
 * Most probably the control sources are not setup correctly.
 *
 * Returns: %TRUE if the controller value could be applied to the object
 * property, %FALSE otherwise
 */
gboolean
gst_control_binding_sync_values (GstControlBinding * binding,
    GstObject * object, GstClockTime timestamp, GstClockTime last_sync)
{
  GstControlBindingClass *klass;
  gboolean ret = FALSE;

  g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE);

  if (binding->disabled)
    return TRUE;

  klass = GST_CONTROL_BINDING_GET_CLASS (binding);

  if (G_LIKELY (klass->sync_values != NULL)) {
    ret = klass->sync_values (binding, object, timestamp, last_sync);
  } else {
    GST_WARNING_OBJECT (binding, "missing sync_values implementation");
  }
  return ret;
}

/**
 * gst_control_binding_get_value:
 * @binding: the control binding
 * @timestamp: the time the control-change should be read from
 *
 * Gets the value for the given controlled property at the requested time.
 *
 * Returns: (nullable): the GValue of the property at the given time,
 * or %NULL if the property isn't controlled.
 */
GValue *
gst_control_binding_get_value (GstControlBinding * binding,
    GstClockTime timestamp)
{
  GstControlBindingClass *klass;
  GValue *ret = NULL;

  g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), NULL);
  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), NULL);

  klass = GST_CONTROL_BINDING_GET_CLASS (binding);

  if (G_LIKELY (klass->get_value != NULL)) {
    ret = klass->get_value (binding, timestamp);
  } else {
    GST_WARNING_OBJECT (binding, "missing get_value implementation");
  }
  return ret;
}

/**
 * gst_control_binding_get_value_array: (skip)
 * @binding: the control binding
 * @timestamp: the time that should be processed
 * @interval: the time spacing between subsequent values
 * @n_values: the number of values
 * @values: (array length=n_values): array to put control-values in
 *
 * Gets a number of values for the given controlled property starting at the
 * requested time. The array @values need to hold enough space for @n_values of
 * the same type as the objects property's type.
 *
 * This function is useful if one wants to e.g. draw a graph of the control
 * curve or apply a control curve sample by sample.
 *
 * The values are unboxed and ready to be used. The similar function
 * gst_control_binding_get_g_value_array() returns the array as #GValues and is
 * more suitable for bindings.
 *
 * Returns: %TRUE if the given array could be filled, %FALSE otherwise
 */
gboolean
gst_control_binding_get_value_array (GstControlBinding * binding,
    GstClockTime timestamp, GstClockTime interval, guint n_values,
    gpointer values)
{
  GstControlBindingClass *klass;
  gboolean ret = FALSE;

  g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE);
  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
  g_return_val_if_fail (values, FALSE);

  klass = GST_CONTROL_BINDING_GET_CLASS (binding);

  if (G_LIKELY (klass->get_value_array != NULL)) {
    ret =
        klass->get_value_array (binding, timestamp, interval, n_values, values);
  } else {
    GST_WARNING_OBJECT (binding, "missing get_value_array implementation");
  }
  return ret;
}

#define CONVERT_ARRAY(type,TYPE) \
{ \
  g##type *v = g_new (g##type,n_values); \
  ret = gst_control_binding_get_value_array (binding, timestamp, interval, \
      n_values, v); \
  if (ret) { \
    for (i = 0; i < n_values; i++) { \
      g_value_init (&values[i], G_TYPE_##TYPE); \
      g_value_set_##type (&values[i], v[i]); \
    } \
  } \
  g_free (v); \
}

/**
 * gst_control_binding_get_g_value_array:
 * @binding: the control binding
 * @timestamp: the time that should be processed
 * @interval: the time spacing between subsequent values
 * @n_values: the number of values
 * @values: (array length=n_values): array to put control-values in
 *
 * Gets a number of #GValues for the given controlled property starting at the
 * requested time. The array @values need to hold enough space for @n_values of
 * #GValue.
 *
 * This function is useful if one wants to e.g. draw a graph of the control
 * curve or apply a control curve sample by sample.
 *
 * Returns: %TRUE if the given array could be filled, %FALSE otherwise
 */
gboolean
gst_control_binding_get_g_value_array (GstControlBinding * binding,
    GstClockTime timestamp, GstClockTime interval, guint n_values,
    GValue * values)
{
  GstControlBindingClass *klass;
  gboolean ret = FALSE;

  g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), FALSE);
  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (interval), FALSE);
  g_return_val_if_fail (values, FALSE);

  klass = GST_CONTROL_BINDING_GET_CLASS (binding);

  if (G_LIKELY (klass->get_g_value_array != NULL)) {
    ret =
        klass->get_g_value_array (binding, timestamp, interval, n_values,
        values);
  } else {
    guint i;
    GType type, base;

    base = type = G_PARAM_SPEC_VALUE_TYPE (GST_CONTROL_BINDING_PSPEC (binding));
    while ((type = g_type_parent (type)))
      base = type;

    GST_INFO_OBJECT (binding, "missing get_g_value_array implementation, we're "
        "emulating it");
    switch (base) {
      case G_TYPE_INT:
        CONVERT_ARRAY (int, INT);
        break;
      case G_TYPE_UINT:
        CONVERT_ARRAY (uint, UINT);
        break;
      case G_TYPE_LONG:
        CONVERT_ARRAY (long, LONG);
        break;
      case G_TYPE_ULONG:
        CONVERT_ARRAY (ulong, ULONG);
        break;
      case G_TYPE_INT64:
        CONVERT_ARRAY (int64, INT64);
        break;
      case G_TYPE_UINT64:
        CONVERT_ARRAY (uint64, UINT64);
        break;
      case G_TYPE_FLOAT:
        CONVERT_ARRAY (float, FLOAT);
        break;
      case G_TYPE_DOUBLE:
        CONVERT_ARRAY (double, DOUBLE);
        break;
      case G_TYPE_BOOLEAN:
        CONVERT_ARRAY (boolean, BOOLEAN);
        break;
      case G_TYPE_ENUM:
      {
        gint *v = g_new (gint, n_values);
        ret = gst_control_binding_get_value_array (binding, timestamp, interval,
            n_values, v);
        if (ret) {
          for (i = 0; i < n_values; i++) {
            g_value_init (&values[i], type);
            g_value_set_enum (&values[i], v[i]);
          }
        }
        g_free (v);
      }
        break;
      default:
        GST_WARNING ("incomplete implementation for paramspec type '%s'",
            G_PARAM_SPEC_TYPE_NAME (GST_CONTROL_BINDING_PSPEC (binding)));
        GST_CONTROL_BINDING_PSPEC (binding) = NULL;
        break;
    }
  }
  return ret;
}

/**
 * gst_control_binding_set_disabled:
 * @binding: the control binding
 * @disabled: boolean that specifies whether to disable the controller
 * or not.
 *
 * This function is used to disable a control binding for some time, i.e.
 * gst_object_sync_values() will do nothing.
 */
void
gst_control_binding_set_disabled (GstControlBinding * binding,
    gboolean disabled)
{
  g_return_if_fail (GST_IS_CONTROL_BINDING (binding));
  binding->disabled = disabled;
}

/**
 * gst_control_binding_is_disabled:
 * @binding: the control binding
 *
 * Check if the control binding is disabled.
 *
 * Returns: %TRUE if the binding is inactive
 */
gboolean
gst_control_binding_is_disabled (GstControlBinding * binding)
{
  g_return_val_if_fail (GST_IS_CONTROL_BINDING (binding), TRUE);
  return ! !binding->disabled;
}
