/* GStreamer
 * Copyright (C) 2005 Stefan Kost <ensonic@users.sf.net>
 *
 * gstchildproxy.c: interface for multi child elements
 *
 * 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:gstchildproxy
 * @short_description: Interface for multi child elements.
 * @see_also: #GstBin
 *
 * This interface abstracts handling of property sets for elements with
 * children. Imagine elements such as mixers or polyphonic generators. They all
 * have multiple #GstPad or some kind of voice objects. Another use case are
 * container elements like #GstBin.
 * The element implementing the interface acts as a parent for those child
 * objects.
 *
 * By implementing this interface the child properties can be accessed from the
 * parent element by using gst_child_proxy_get() and gst_child_proxy_set().
 *
 * Property names are written as "child-name::property-name". The whole naming
 * scheme is recursive. Thus "child1::child2::property" is valid too, if
 * "child1" and "child2" implement the #GstChildProxy interface.
 */

#include "gst_private.h"

#include "gstchildproxy.h"
#include <gobject/gvaluecollector.h>

/* signals */
enum
{
  CHILD_ADDED,
  CHILD_REMOVED,
  LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = { 0 };

static GObject *
gst_child_proxy_default_get_child_by_name (GstChildProxy * parent,
    const gchar * name)
{
  guint count, i;
  GObject *object, *result;
  gchar *object_name;

  g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL);
  g_return_val_if_fail (name != NULL, NULL);

  result = NULL;

  count = gst_child_proxy_get_children_count (parent);
  for (i = 0; i < count; i++) {
    gboolean eq;

    if (!(object = gst_child_proxy_get_child_by_index (parent, i)))
      continue;

    if (!GST_IS_OBJECT (object)) {
      goto next;
    }
    object_name = gst_object_get_name (GST_OBJECT_CAST (object));
    if (object_name == NULL) {
      g_warning ("child %u of parent %s has no name", i,
          GST_OBJECT_NAME (parent));
      goto next;
    }
    eq = g_str_equal (object_name, name);
    g_free (object_name);

    if (eq) {
      result = object;
      break;
    }
  next:
    g_object_unref (object);
  }
  return result;
}


/**
 * gst_child_proxy_get_child_by_name:
 * @parent: the parent object to get the child from
 * @name: the childs name
 *
 * Looks up a child element by the given name.
 *
 * This virtual method has a default implementation that uses #GstObject
 * together with gst_object_get_name(). If the interface is to be used with
 * #GObjects, this methods needs to be overridden.
 *
 * Returns: (transfer full): the child object or %NULL if not found. Unref
 *     after usage.
 *
 * MT safe.
 */
GObject *
gst_child_proxy_get_child_by_name (GstChildProxy * parent, const gchar * name)
{
  g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), 0);

  return (GST_CHILD_PROXY_GET_INTERFACE (parent)->get_child_by_name (parent,
          name));
}

/**
 * gst_child_proxy_get_child_by_index:
 * @parent: the parent object to get the child from
 * @index: the childs position in the child list
 *
 * Fetches a child by its number.
 *
 * Returns: (transfer full): the child object or %NULL if not found (index
 *     too high). Unref after usage.
 *
 * MT safe.
 */
GObject *
gst_child_proxy_get_child_by_index (GstChildProxy * parent, guint index)
{
  g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), NULL);

  return (GST_CHILD_PROXY_GET_INTERFACE (parent)->get_child_by_index (parent,
          index));
}

/**
 * gst_child_proxy_get_children_count:
 * @parent: the parent object
 *
 * Gets the number of child objects this parent contains.
 *
 * Returns: the number of child objects
 *
 * MT safe.
 */
guint
gst_child_proxy_get_children_count (GstChildProxy * parent)
{
  g_return_val_if_fail (GST_IS_CHILD_PROXY (parent), 0);

  return (GST_CHILD_PROXY_GET_INTERFACE (parent)->get_children_count (parent));
}

/**
 * gst_child_proxy_lookup:
 * @object: child proxy object to lookup the property in
 * @name: name of the property to look up
 * @target: (out) (allow-none) (transfer full): pointer to a #GObject that
 *     takes the real object to set property on
 * @pspec: (out) (allow-none) (transfer none): pointer to take the #GParamSpec
 *     describing the property
 *
 * Looks up which object and #GParamSpec would be effected by the given @name.
 *
 * MT safe.
 *
 * Returns: TRUE if @target and @pspec could be found. FALSE otherwise. In that
 * case the values for @pspec and @target are not modified. Unref @target after
 * usage. For plain GObjects @target is the same as @object.
 */
gboolean
gst_child_proxy_lookup (GstChildProxy * object, const gchar * name,
    GObject ** target, GParamSpec ** pspec)
{
  GObject *obj;
  gboolean res = FALSE;
  gchar **names, **current;

  g_return_val_if_fail (GST_IS_CHILD_PROXY (object), FALSE);
  g_return_val_if_fail (name != NULL, FALSE);

  obj = g_object_ref (object);

  current = names = g_strsplit (name, "::", -1);
  /* find the owner of the property */
  while (current[1]) {
    GObject *next;

    if (!GST_IS_CHILD_PROXY (obj)) {
      GST_INFO
          ("object %s is not a parent, so you cannot request a child by name %s",
          (GST_IS_OBJECT (obj) ? GST_OBJECT_NAME (obj) : ""), current[0]);
      break;
    }
    next = gst_child_proxy_get_child_by_name (GST_CHILD_PROXY (obj),
        current[0]);
    if (!next) {
      GST_INFO ("no such object %s", current[0]);
      break;
    }
    g_object_unref (obj);
    obj = next;
    current++;
  }

  /* look for psec */
  if (current[1] == NULL) {
    GParamSpec *spec =
        g_object_class_find_property (G_OBJECT_GET_CLASS (obj), current[0]);
    if (spec == NULL) {
      GST_INFO ("no param spec named %s", current[0]);
    } else {
      if (pspec)
        *pspec = spec;
      if (target) {
        g_object_ref (obj);
        *target = obj;
      }
      res = TRUE;
    }
  }
  g_object_unref (obj);
  g_strfreev (names);
  return res;
}

/**
 * gst_child_proxy_get_property:
 * @object: object to query
 * @name: name of the property
 * @value: (out caller-allocates): a #GValue that should take the result.
 *
 * Gets a single property using the GstChildProxy mechanism.
 * You are responsible for freeing it by calling g_value_unset()
 */
void
gst_child_proxy_get_property (GstChildProxy * object, const gchar * name,
    GValue * value)
{
  GParamSpec *pspec;
  GObject *target;

  g_return_if_fail (GST_IS_CHILD_PROXY (object));
  g_return_if_fail (name != NULL);
  g_return_if_fail (G_IS_VALUE (value));

  if (!gst_child_proxy_lookup (object, name, &target, &pspec))
    goto not_found;

  g_object_get_property (target, pspec->name, value);
  g_object_unref (target);

  return;

not_found:
  {
    g_warning ("no property %s in object %s", name,
        (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""));
    return;
  }
}

/**
 * gst_child_proxy_get_valist:
 * @object: the object to query
 * @first_property_name: name of the first property to get
 * @var_args: return location for the first property, followed optionally by more name/return location pairs, followed by NULL
 *
 * Gets properties of the parent object and its children.
 */
void
gst_child_proxy_get_valist (GstChildProxy * object,
    const gchar * first_property_name, va_list var_args)
{
  const gchar *name;
  gchar *error = NULL;
  GValue value = { 0, };
  GParamSpec *pspec;
  GObject *target;

  g_return_if_fail (GST_IS_CHILD_PROXY (object));

  name = first_property_name;

  /* iterate over pairs */
  while (name) {
    if (!gst_child_proxy_lookup (object, name, &target, &pspec))
      goto not_found;

    g_value_init (&value, pspec->value_type);
    g_object_get_property (target, pspec->name, &value);
    g_object_unref (target);

    G_VALUE_LCOPY (&value, var_args, 0, &error);
    if (error)
      goto cant_copy;
    g_value_unset (&value);
    name = va_arg (var_args, gchar *);
  }
  return;

not_found:
  {
    g_warning ("no property %s in object %s", name,
        (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""));
    return;
  }
cant_copy:
  {
    g_warning ("error copying value %s in object %s: %s", pspec->name,
        (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""), error);
    g_value_unset (&value);
    return;
  }
}

/**
 * gst_child_proxy_get:
 * @object: the parent object
 * @first_property_name: name of the first property to get
 * @...: return location for the first property, followed optionally by more name/return location pairs, followed by NULL
 *
 * Gets properties of the parent object and its children.
 */
void
gst_child_proxy_get (GstChildProxy * object, const gchar * first_property_name,
    ...)
{
  va_list var_args;

  g_return_if_fail (GST_IS_CHILD_PROXY (object));

  va_start (var_args, first_property_name);
  gst_child_proxy_get_valist (object, first_property_name, var_args);
  va_end (var_args);
}

/**
 * gst_child_proxy_set_property:
 * @object: the parent object
 * @name: name of the property to set
 * @value: new #GValue for the property
 *
 * Sets a single property using the GstChildProxy mechanism.
 */
void
gst_child_proxy_set_property (GstChildProxy * object, const gchar * name,
    const GValue * value)
{
  GParamSpec *pspec;
  GObject *target;

  g_return_if_fail (GST_IS_CHILD_PROXY (object));
  g_return_if_fail (name != NULL);
  g_return_if_fail (G_IS_VALUE (value));

  if (!gst_child_proxy_lookup (object, name, &target, &pspec))
    goto not_found;

  g_object_set_property (target, pspec->name, value);
  g_object_unref (target);
  return;

not_found:
  {
    g_warning ("cannot set property %s on object %s", name,
        (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""));
    return;
  }
}

/**
 * gst_child_proxy_set_valist:
 * @object: the parent object
 * @first_property_name: name of the first property to set
 * @var_args: value for the first property, followed optionally by more name/value pairs, followed by NULL
 *
 * Sets properties of the parent object and its children.
 */
void
gst_child_proxy_set_valist (GstChildProxy * object,
    const gchar * first_property_name, va_list var_args)
{
  const gchar *name;
  gchar *error = NULL;
  GValue value = { 0, };
  GParamSpec *pspec;
  GObject *target;

  g_return_if_fail (GST_IS_CHILD_PROXY (object));

  name = first_property_name;

  /* iterate over pairs */
  while (name) {
    if (!gst_child_proxy_lookup (object, name, &target, &pspec))
      goto not_found;

    G_VALUE_COLLECT_INIT (&value, pspec->value_type, var_args,
        G_VALUE_NOCOPY_CONTENTS, &error);

    if (error)
      goto cant_copy;

    g_object_set_property (target, pspec->name, &value);
    g_object_unref (target);

    g_value_unset (&value);
    name = va_arg (var_args, gchar *);
  }
  return;

not_found:
  {
    g_warning ("no property %s in object %s", name,
        (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""));
    return;
  }
cant_copy:
  {
    g_warning ("error copying value %s in object %s: %s", pspec->name,
        (GST_IS_OBJECT (object) ? GST_OBJECT_NAME (object) : ""), error);
    g_value_unset (&value);
    g_object_unref (target);
    return;
  }
}

/**
 * gst_child_proxy_set:
 * @object: the parent object
 * @first_property_name: name of the first property to set
 * @...: value for the first property, followed optionally by more name/value pairs, followed by NULL
 *
 * Sets properties of the parent object and its children.
 */
void
gst_child_proxy_set (GstChildProxy * object, const gchar * first_property_name,
    ...)
{
  va_list var_args;

  g_return_if_fail (GST_IS_CHILD_PROXY (object));

  va_start (var_args, first_property_name);
  gst_child_proxy_set_valist (object, first_property_name, var_args);
  va_end (var_args);
}

/**
 * gst_child_proxy_child_added:
 * @parent: the parent object
 * @child: the newly added child
 * @name: the name of the new child
 *
 * Emits the "child-added" signal.
 */
void
gst_child_proxy_child_added (GstChildProxy * parent, GObject * child,
    const gchar * name)
{
  g_signal_emit (parent, signals[CHILD_ADDED], 0, child, name);
}

/**
 * gst_child_proxy_child_removed:
 * @parent: the parent object
 * @child: the removed child
 * @name: the name of the old child
 *
 * Emits the "child-removed" signal.
 */
void
gst_child_proxy_child_removed (GstChildProxy * parent, GObject * child,
    const gchar * name)
{
  g_signal_emit (parent, signals[CHILD_REMOVED], 0, child, name);
}

/* gobject methods */

static void
gst_child_proxy_class_init (gpointer g_class, gpointer class_data)
{
  GstChildProxyInterface *iface = (GstChildProxyInterface *) g_class;

  iface->get_child_by_name = gst_child_proxy_default_get_child_by_name;
}

static void
gst_child_proxy_base_init (gpointer g_class)
{
  static gboolean initialized = FALSE;

  if (!initialized) {
    /* create interface signals and properties here. */
    /**
     * GstChildProxy::child-added:
     * @child_proxy: the #GstChildProxy
     * @object: the #GObject that was added
     * @name: the name of the new child
     *
     * Will be emitted after the @object was added to the @child_proxy.
     */
    signals[CHILD_ADDED] =
        g_signal_new ("child-added", G_TYPE_FROM_CLASS (g_class),
        G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
            child_added), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE,
        2, G_TYPE_OBJECT, G_TYPE_STRING);

    /**
     * GstChildProxy::child-removed:
     * @child_proxy: the #GstChildProxy
     * @object: the #GObject that was removed
     * @name: the name of the old child
     *
     * Will be emitted after the @object was removed from the @child_proxy.
     */
    signals[CHILD_REMOVED] =
        g_signal_new ("child-removed", G_TYPE_FROM_CLASS (g_class),
        G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstChildProxyInterface,
            child_removed), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE,
        2, G_TYPE_OBJECT, G_TYPE_STRING);

    initialized = TRUE;
  }
}

GType
gst_child_proxy_get_type (void)
{
  static volatile gsize type = 0;

  if (g_once_init_enter (&type)) {
    GType _type;
    static const GTypeInfo info = {
      sizeof (GstChildProxyInterface),
      gst_child_proxy_base_init,        /* base_init */
      NULL,                     /* base_finalize */
      gst_child_proxy_class_init,       /* class_init */
      NULL,                     /* class_finalize */
      NULL,                     /* class_data */
      0,
      0,                        /* n_preallocs */
      NULL                      /* instance_init */
    };

    _type =
        g_type_register_static (G_TYPE_INTERFACE, "GstChildProxy", &info, 0);

    g_type_interface_add_prerequisite (_type, G_TYPE_OBJECT);
    g_once_init_leave (&type, (gsize) _type);
  }
  return type;
}
