/* GStreamer PropertyProbe
 * Copyright (C) 2003 David Schleef <ds@schleef.org>
 *
 * property_probe.c: property_probe design virtual class function wrappers
 *
 * 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.
 */

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

#include <string.h>

#include "propertyprobe.h"

enum {
  SIGNAL_PROBE_NEEDED,
  LAST_SIGNAL
};

static void gst_property_probe_iface_init (GstPropertyProbeInterface *iface);

static guint gst_property_probe_signals[LAST_SIGNAL] = { 0 };

GType
gst_property_probe_get_type (void)
{
  static GType gst_property_probe_type = 0;

  if (!gst_property_probe_type) {
    static const GTypeInfo gst_property_probe_info = {
      sizeof (GstPropertyProbeInterface),
      (GBaseInitFunc) gst_property_probe_iface_init,
      NULL,
      NULL,
      NULL,
      NULL,
      0,
      0,
      NULL,
    };

    gst_property_probe_type =
	g_type_register_static (G_TYPE_INTERFACE,
				"GstPropertyProbe",
				&gst_property_probe_info, 0);
  }

  return gst_property_probe_type;
}

static void
gst_property_probe_iface_init (GstPropertyProbeInterface *iface)
{
  static gboolean initialized = FALSE;

  if (!initialized) {
    gst_property_probe_signals[SIGNAL_PROBE_NEEDED] =
      g_signal_new ("probe_needed", G_TYPE_FROM_CLASS (iface), G_SIGNAL_RUN_LAST,
		    G_STRUCT_OFFSET (GstPropertyProbeInterface, probe_needed),
		    NULL, NULL, g_cclosure_marshal_VOID__POINTER,
		    G_TYPE_NONE, 1, G_TYPE_POINTER);
    initialized = TRUE;
  }

  /* default virtual functions */
  iface->get_properties = NULL;
  iface->get_values     = NULL;
}

const GList *
gst_property_probe_get_properties (GstPropertyProbe *probe)
{
  GstPropertyProbeInterface *iface;

  g_return_val_if_fail (probe != NULL, NULL);
                                                                                
  iface = GST_PROPERTY_PROBE_GET_IFACE (probe);
                                                                                
  if (iface->get_properties)
    return iface->get_properties (probe);
                                                                                
  return NULL;
}

const GParamSpec *
gst_property_probe_get_property (GstPropertyProbe *probe,
				 const gchar      *name)
{
  const GList *pspecs = gst_property_probe_get_properties (probe);

  g_return_val_if_fail (probe != NULL, NULL);
  g_return_val_if_fail (name != NULL, NULL);

  while (pspecs) {
    const GParamSpec *pspec = pspecs->data;

    if (!strcmp (pspec->name, name))
      return pspec;

    pspecs = pspecs->next;
  }

  return NULL;
}

void
gst_property_probe_probe_property (GstPropertyProbe *probe,
				   const GParamSpec *pspec)
{
  GstPropertyProbeInterface *iface;

  g_return_if_fail (probe != NULL);
  g_return_if_fail (pspec != NULL);

  iface = GST_PROPERTY_PROBE_GET_IFACE (probe);

  if (iface->probe_property)
    iface->probe_property (probe, pspec->param_id, pspec);
}

void
gst_property_probe_probe_property_name (GstPropertyProbe *probe,
					const gchar      *name)
{
  const GParamSpec *pspec;

  g_return_if_fail (probe != NULL);
  g_return_if_fail (name != NULL);

  pspec = g_object_class_find_property (G_OBJECT_CLASS (probe), name);
  if (!pspec) {
    g_warning ("No such property %s", name);
    return;
  }

  gst_property_probe_probe_property (probe, pspec);
}

gboolean
gst_property_probe_needs_probe (GstPropertyProbe *probe,
				const GParamSpec *pspec)
{
  GstPropertyProbeInterface *iface;

  g_return_val_if_fail (probe != NULL, FALSE);
  g_return_val_if_fail (pspec != NULL, FALSE);

  iface = GST_PROPERTY_PROBE_GET_IFACE (probe);

  if (iface->needs_probe)
    return iface->needs_probe (probe, pspec->param_id, pspec);

  return FALSE;
}

gboolean
gst_property_probe_needs_probe_name (GstPropertyProbe *probe,
				     const gchar      *name)
{
  const GParamSpec *pspec;

  g_return_val_if_fail (probe != NULL, FALSE);
  g_return_val_if_fail (name != NULL, FALSE);

  pspec = g_object_class_find_property (G_OBJECT_CLASS (probe), name);
  if (!pspec) {
    g_warning ("No such property %s", name);
    return FALSE;
  }

  return gst_property_probe_needs_probe (probe, pspec);
}
                                                                               
GValueArray *
gst_property_probe_get_values (GstPropertyProbe *probe,
			       const GParamSpec *pspec)
{
  GstPropertyProbeInterface *iface;

  g_return_val_if_fail (probe != NULL, NULL);
  g_return_val_if_fail (pspec != NULL, NULL);

  iface = GST_PROPERTY_PROBE_GET_IFACE (probe);

  if (iface->get_values)
    return iface->get_values (probe, pspec->param_id, pspec);

  return NULL;
}

GValueArray *
gst_property_probe_get_values_name (GstPropertyProbe *probe,
				    const gchar      *name)
{
  const GParamSpec *pspec;

  g_return_val_if_fail (probe != NULL, NULL);
  g_return_val_if_fail (name != NULL, NULL);

  pspec = g_object_class_find_property (G_OBJECT_CLASS (probe), name);
  if (!pspec) {
    g_warning ("No such property %s", name);
    return NULL;
  }

  return gst_property_probe_get_values (probe, pspec);
}


GValueArray *
gst_property_probe_probe_and_get_values (GstPropertyProbe *probe,
					 const GParamSpec *pspec)
{
  GstPropertyProbeInterface *iface;

  g_return_val_if_fail (probe != NULL, NULL);
  g_return_val_if_fail (pspec != NULL, NULL);

  iface = GST_PROPERTY_PROBE_GET_IFACE (probe);

  if (gst_property_probe_needs_probe (probe, pspec))
    gst_property_probe_probe_property (probe, pspec);

  return gst_property_probe_get_values (probe, pspec);
}

GValueArray *
gst_property_probe_probe_and_get_values_name (GstPropertyProbe *probe,
					      const gchar      *name)
{
  const GParamSpec *pspec;

  g_return_val_if_fail (probe != NULL, NULL);
  g_return_val_if_fail (name != NULL, NULL);

  pspec = g_object_class_find_property (G_OBJECT_CLASS (probe), name);
  if (!pspec) {
    g_warning ("No such property %s", name);
    return NULL;
  }

  return gst_property_probe_probe_and_get_values (probe, pspec);
}