/*
 * Copyright (C) 2018 Centricular Ltd.
 *   Author: Sebastian Dröge <sebastian@centricular.com>
 *   Author: Nirbheek Chauhan <nirbheek@centricular.com>
 *
 * 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:element-proxysrc
 * @title: proxysrc
 *
 * Proxysrc is a source element that proxies events, queries, and buffers from
 * another pipeline that contains a matching proxysink element. The purpose is
 * to allow two decoupled pipelines to function as though they are one without
 * having to manually shuttle buffers, events, queries, etc between the two.
 *
 * The element queues buffers from the matching proxysink to an internal queue,
 * so everything downstream is properly decoupled from the upstream pipeline.
 * However, the queue may get filled up if the downstream pipeline does not
 * accept buffers quickly enough; perhaps because it is not yet PLAYING.
 *
 * ## Usage
 * 
 * |[<!-- language="C" -->
 * GstElement *pipe1, *pipe2, *psink, *psrc;
 * GstClock *clock;
 *
 * pipe1 = gst_parse_launch ("audiotestsrc ! proxysink name=psink", NULL);
 * psink = gst_bin_get_by_name (GST_BIN (pipe1), "psink");
 *
 * pipe2 = gst_parse_launch ("proxysrc name=psrc ! autoaudiosink", NULL);
 * psrc = gst_bin_get_by_name (GST_BIN (pipe2), "psrc");
 *
 * // Connect the two pipelines
 * g_object_set (psrc, "proxysink", psink, NULL);
 *
 * // Both pipelines must agree on the timing information or we'll get glitches
 * // or overruns/underruns. Ideally, we should tell pipe1 to use the same clock
 * // as pipe2, but since that will be set asynchronously to the audio clock, it
 * // is simpler and likely accurate enough to use the system clock for both
 * // pipelines. If no element in either pipeline will provide a clock, this
 * // is not needed.
 * clock = gst_system_clock_obtain ();
 * gst_pipeline_use_clock (GST_PIPELINE (pipe1), clock);
 * gst_pipeline_use_clock (GST_PIPELINE (pipe2), clock);
 * g_object_unref (clock);
 *
 * // This is not really needed in this case since the pipelines are created and
 * // started at the same time. However, an application that dynamically
 * // generates pipelines must ensure that all the pipelines that will be
 * // connected together share the same base time.
 * gst_element_set_base_time (pipe1, 0);
 * gst_element_set_base_time (pipe2, 0);
 *
 * gst_element_set_state (pipe1, GST_STATE_PLAYING);
 * gst_element_set_state (pipe2, GST_STATE_PLAYING);
 * ]|
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstproxysrc.h"
#include "gstproxysink.h"
#include "gstproxy-priv.h"

#define GST_CAT_DEFAULT gst_proxy_src_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);

static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS_ANY);

enum
{
  PROP_0,
  PROP_PROXYSINK,
};

/* We're not subclassing from basesrc because we don't want any of the special
 * handling it has for events/queries/etc. We just pass-through everything. */

/* Our parent type is a GstBin instead of GstElement because we contain a queue
 * element */
#define parent_class gst_proxy_src_parent_class
G_DEFINE_TYPE (GstProxySrc, gst_proxy_src, GST_TYPE_BIN);

static gboolean gst_proxy_src_internal_src_query (GstPad * pad,
    GstObject * parent, GstQuery * query);
static gboolean gst_proxy_src_internal_src_event (GstPad * pad,
    GstObject * parent, GstEvent * event);

static GstStateChangeReturn gst_proxy_src_change_state (GstElement * element,
    GstStateChange transition);
static void gst_proxy_src_dispose (GObject * object);

static void
gst_proxy_src_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * spec)
{
  GstProxySrc *self = GST_PROXY_SRC (object);

  switch (prop_id) {
    case PROP_PROXYSINK:
      g_value_take_object (value, g_weak_ref_get (&self->proxysink));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
      break;
  }
}

static void
gst_proxy_src_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * spec)
{
  GstProxySrc *self = GST_PROXY_SRC (object);
  GstProxySink *sink;

  switch (prop_id) {
    case PROP_PROXYSINK:
      sink = g_value_dup_object (value);
      if (sink == NULL) {
        /* Unset proxysrc property on the existing proxysink to break the
         * connection in that direction */
        GstProxySink *old_sink = g_weak_ref_get (&self->proxysink);
        if (old_sink) {
          gst_proxy_sink_set_proxysrc (old_sink, NULL);
          g_object_unref (old_sink);
        }
        g_weak_ref_set (&self->proxysink, NULL);
      } else {
        /* Set proxysrc property on the new proxysink to point to us */
        gst_proxy_sink_set_proxysrc (sink, self);
        g_weak_ref_set (&self->proxysink, sink);
        g_object_unref (sink);
      }
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
  }
}

static void
gst_proxy_src_class_init (GstProxySrcClass * klass)
{
  GObjectClass *gobject_class = (GObjectClass *) klass;
  GstElementClass *gstelement_class = (GstElementClass *) klass;

  GST_DEBUG_CATEGORY_INIT (gst_proxy_src_debug, "proxysrc", 0, "proxy sink");

  gobject_class->dispose = gst_proxy_src_dispose;

  gobject_class->get_property = gst_proxy_src_get_property;
  gobject_class->set_property = gst_proxy_src_set_property;

  g_object_class_install_property (gobject_class, PROP_PROXYSINK,
      g_param_spec_object ("proxysink", "Proxysink", "Matching proxysink",
          GST_TYPE_PROXY_SINK, G_PARAM_READWRITE));

  gstelement_class->change_state = gst_proxy_src_change_state;
  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&src_template));

  gst_element_class_set_static_metadata (gstelement_class, "Proxy source",
      "Source", "Proxy source for internal process communication",
      "Sebastian Dröge <sebastian@centricular.com>");
}

static void
gst_proxy_src_init (GstProxySrc * self)
{
  GstPad *srcpad, *sinkpad;
  GstPadTemplate *templ;

  GST_OBJECT_FLAG_SET (self, GST_ELEMENT_FLAG_SOURCE);

  /* We feed incoming buffers into a queue to decouple the downstream pipeline
   * from the upstream pipeline */
  self->queue = gst_element_factory_make ("queue", NULL);
  gst_bin_add (GST_BIN (self), self->queue);

  srcpad = gst_element_get_static_pad (self->queue, "src");
  templ = gst_static_pad_template_get (&src_template);
  self->srcpad = gst_ghost_pad_new_from_template ("src", srcpad, templ);
  gst_object_unref (templ);
  gst_object_unref (srcpad);

  gst_element_add_pad (GST_ELEMENT (self), self->srcpad);

  /* A dummy sinkpad that's not actually used anywhere
   * Explanation for why this is needed is below */
  self->dummy_sinkpad = gst_pad_new ("dummy_sinkpad", GST_PAD_SINK);
  gst_object_set_parent (GST_OBJECT (self->dummy_sinkpad), GST_OBJECT (self));

  self->internal_srcpad = gst_pad_new ("internal_src", GST_PAD_SRC);
  gst_object_set_parent (GST_OBJECT (self->internal_srcpad),
      GST_OBJECT (self->dummy_sinkpad));
  gst_pad_set_event_function (self->internal_srcpad,
      gst_proxy_src_internal_src_event);
  gst_pad_set_query_function (self->internal_srcpad,
      gst_proxy_src_internal_src_query);

  /* We need to link internal_srcpad from proxysink to the sinkpad of our
   * queue. However, two pads can only be linked if they share a common parent.
   * Above, we set the parent of the dummy_sinkpad as proxysrc, and then we set
   * the parent of internal_srcpad as dummy_sinkpad. This causes both these pads
   * to share a parent allowing us to link them.
   * Yes, this is a hack/workaround. */
  sinkpad = gst_element_get_static_pad (self->queue, "sink");
  gst_pad_link (self->internal_srcpad, sinkpad);
  gst_object_unref (sinkpad);
}

static void
gst_proxy_src_dispose (GObject * object)
{
  GstProxySrc *self = GST_PROXY_SRC (object);

  gst_object_unparent (GST_OBJECT (self->dummy_sinkpad));
  self->dummy_sinkpad = NULL;

  gst_object_unparent (GST_OBJECT (self->internal_srcpad));
  self->internal_srcpad = NULL;

  g_weak_ref_set (&self->proxysink, NULL);

  G_OBJECT_CLASS (gst_proxy_src_parent_class)->dispose (object);
}

static GstStateChangeReturn
gst_proxy_src_change_state (GstElement * element, GstStateChange transition)
{
  GstElementClass *gstelement_class =
      GST_ELEMENT_CLASS (gst_proxy_src_parent_class);
  GstProxySrc *self = GST_PROXY_SRC (element);
  GstStateChangeReturn ret;

  ret = gstelement_class->change_state (element, transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      ret = GST_STATE_CHANGE_NO_PREROLL;
      gst_pad_set_active (self->internal_srcpad, TRUE);
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_pad_set_active (self->internal_srcpad, FALSE);
      break;
    default:
      break;
  }

  return ret;
}

static gboolean
gst_proxy_src_internal_src_query (GstPad * pad, GstObject * parent,
    GstQuery * query)
{
  GstProxySrc *self = GST_PROXY_SRC (gst_object_get_parent (parent));
  GstProxySink *sink;
  gboolean ret = FALSE;

  if (!self)
    return ret;

  GST_LOG_OBJECT (pad, "Handling query of type '%s'",
      gst_query_type_get_name (GST_QUERY_TYPE (query)));

  sink = g_weak_ref_get (&self->proxysink);
  if (sink) {
    GstPad *sinkpad;
    sinkpad = gst_proxy_sink_get_internal_sinkpad (sink);

    ret = gst_pad_peer_query (sinkpad, query);
    gst_object_unref (sinkpad);
    gst_object_unref (sink);
  }

  gst_object_unref (self);

  return ret;
}

static gboolean
gst_proxy_src_internal_src_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstProxySrc *self = GST_PROXY_SRC (gst_object_get_parent (parent));
  GstProxySink *sink;
  gboolean ret = FALSE;

  if (!self)
    return ret;

  GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event));

  sink = g_weak_ref_get (&self->proxysink);
  if (sink) {
    GstPad *sinkpad;
    sinkpad = gst_proxy_sink_get_internal_sinkpad (sink);

    ret = gst_pad_push_event (sinkpad, event);
    gst_object_unref (sinkpad);
    gst_object_unref (sink);
  } else
    gst_event_unref (event);


  gst_object_unref (self);

  return ret;
}

/* Wrapper function for accessing private member */
GstPad *
gst_proxy_src_get_internal_srcpad (GstProxySrc * self)
{
  return gst_object_ref (self->internal_srcpad);
}
