/* 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, 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:
 * @childproxy: 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 * childproxy, const gchar * name,
    GObject ** target, GParamSpec ** pspec)
{
  GObject *object;
  gboolean res = FALSE;
  gchar **names, **current;

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

  object = g_object_ref (childproxy);

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

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

  /* look for psec */
  if (current[1] == NULL) {
    GParamSpec *spec =
        g_object_class_find_property (G_OBJECT_GET_CLASS (object), current[0]);
    if (spec == NULL) {
      GST_INFO ("no param spec named %s", current[0]);
    } else {
      if (pspec)
        *pspec = spec;
      if (target) {
        g_object_ref (object);
        *target = object;
      }
      res = TRUE;
    }
  }
  g_object_unref (object);
  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;
}
