/* GStreamer
 * Copyright (C) 2010, 2012 Alexander Saprykin <xelfium@gmail.com>
 *
 * gsttocsetter.c: interface for TOC setting on 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:gsttocsetter
 * @short_description: Element interface that allows setting and retrieval
 *                     of the TOC
 *
 * Element interface that allows setting of the TOC.
 *
 * Elements that support some kind of chapters or editions (or tracks like in
 * the FLAC cue sheet) will implement this interface.
 * 
 * If you just want to retrieve the TOC in your application then all you
 * need to do is watch for TOC messages on your pipeline's bus (or you can
 * perform TOC query). This interface is only for setting TOC data, not for
 * extracting it. To set TOC from the application, find proper tocsetter element
 * and set TOC using gst_toc_setter_set_toc().
 * 
 * Elements implementing the #GstTocSetter interface can extend existing TOC
 * by getting extend UID for that (you can use gst_toc_find_entry() to retrieve it)
 * with any TOC entries received from downstream.
 */


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

#include "gst_private.h"
#include "gsttocsetter.h"
#include <gobject/gvaluecollector.h>
#include <string.h>

static GQuark gst_toc_key;

G_DEFINE_INTERFACE_WITH_CODE (GstTocSetter, gst_toc_setter, GST_TYPE_ELEMENT,
    gst_toc_key = g_quark_from_static_string ("gst-toc-setter-data"););

static void
gst_toc_setter_default_init (GstTocSetterInterface * klass)
{
  /* nothing to do here, it's a dummy interface */
}

typedef struct
{
  GstToc *toc;
  GMutex lock;
} GstTocData;

static void
gst_toc_data_free (gpointer p)
{
  GstTocData *data = (GstTocData *) p;

  if (data->toc)
    gst_toc_unref (data->toc);

  g_mutex_clear (&data->lock);

  g_slice_free (GstTocData, data);
}

static GstTocData *
gst_toc_setter_get_data (GstTocSetter * setter)
{
  GstTocData *data;

  data = g_object_get_qdata (G_OBJECT (setter), gst_toc_key);
  if (!data) {
    static GMutex create_mutex;

    /* make sure no other thread is creating a GstTocData at the same time */
    g_mutex_lock (&create_mutex);
    data = g_object_get_qdata (G_OBJECT (setter), gst_toc_key);
    if (!data) {
      data = g_slice_new (GstTocData);
      g_mutex_init (&data->lock);
      data->toc = NULL;
      g_object_set_qdata_full (G_OBJECT (setter), gst_toc_key, data,
          gst_toc_data_free);
    }
    g_mutex_unlock (&create_mutex);
  }

  return data;
}

/**
 * gst_toc_setter_reset:
 * @setter: a #GstTocSetter.
 *
 * Reset the internal TOC. Elements should call this from within the
 * state-change handler.
 */
void
gst_toc_setter_reset (GstTocSetter * setter)
{
  g_return_if_fail (GST_IS_TOC_SETTER (setter));

  gst_toc_setter_set_toc (setter, NULL);
}

/**
 * gst_toc_setter_get_toc:
 * @setter: a #GstTocSetter.
 *
 * Return current TOC the setter uses. The TOC should not be
 * modified without making it writable first.
 *
 *
 * Returns: (transfer full): TOC set, or %NULL. Unref with gst_toc_unref()
 *     when no longer needed
 */
GstToc *
gst_toc_setter_get_toc (GstTocSetter * setter)
{
  GstTocData *data;
  GstToc *ret = NULL;

  g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);

  data = gst_toc_setter_get_data (setter);
  g_mutex_lock (&data->lock);

  if (data->toc != NULL)
    ret = gst_toc_ref (data->toc);

  g_mutex_unlock (&data->lock);

  return ret;
}

/**
 * gst_toc_setter_set_toc:
 * @setter: a #GstTocSetter.
 * @toc: (allow-none): a #GstToc to set.
 *
 * Set the given TOC on the setter. Previously set TOC will be
 * unreffed before setting a new one.
 */
void
gst_toc_setter_set_toc (GstTocSetter * setter, GstToc * toc)
{
  GstTocData *data;

  g_return_if_fail (GST_IS_TOC_SETTER (setter));

  data = gst_toc_setter_get_data (setter);

  g_mutex_lock (&data->lock);

  if (data->toc != toc) {
    if (data->toc)
      gst_toc_unref (data->toc);

    data->toc = (toc) ? gst_toc_ref (toc) : NULL;
  }

  g_mutex_unlock (&data->lock);
}
