/* GStreamer
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
 * Copyright (C) <2003> David Schleef <ds@schleef.org>
 *
 * 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.
 */

/*
 * This file was (probably) generated from gstnavseek.c,
 * gstnavseek.c,v 1.7 2003/11/08 02:48:59 dschleef Exp 
 */

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

#include "gstnavseek.h"
#include <string.h>
#include <math.h>

enum
{
  ARG_0,
  ARG_SEEKOFFSET
};

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

GstStaticPadTemplate navseek_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS_ANY);

static gboolean gst_navseek_sink_event (GstBaseTransform * trans,
    GstEvent * event);
static GstFlowReturn gst_navseek_transform_ip (GstBaseTransform * basetrans,
    GstBuffer * buf);
static gboolean gst_navseek_src_event (GstBaseTransform * trans,
    GstEvent * event);
static gboolean gst_navseek_stop (GstBaseTransform * trans);
static gboolean gst_navseek_start (GstBaseTransform * trans);

static void gst_navseek_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_navseek_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);

GType gst_navseek_get_type (void);
#define gst_navseek_parent_class parent_class
G_DEFINE_TYPE (GstNavSeek, gst_navseek, GST_TYPE_BASE_TRANSFORM);

static void
gst_navseek_class_init (GstNavSeekClass * klass)
{
  GstBaseTransformClass *gstbasetrans_class;
  GstElementClass *element_class;
  GObjectClass *gobject_class;

  gobject_class = G_OBJECT_CLASS (klass);
  element_class = GST_ELEMENT_CLASS (klass);
  gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);

  gobject_class->set_property = gst_navseek_set_property;
  gobject_class->get_property = gst_navseek_get_property;

  g_object_class_install_property (gobject_class,
      ARG_SEEKOFFSET, g_param_spec_double ("seek-offset", "Seek Offset",
          "Time in seconds to seek by", 0.0, G_MAXDOUBLE, 5.0,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&navseek_sink_template));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&navseek_src_template));

  gst_element_class_set_static_metadata (element_class,
      "Seek based on left-right arrows", "Filter/Video",
      "Seek based on navigation keys left-right",
      "Jan Schmidt <thaytan@mad.scientist.com>");

  gstbasetrans_class->src_event = GST_DEBUG_FUNCPTR (gst_navseek_src_event);
  gstbasetrans_class->sink_event = GST_DEBUG_FUNCPTR (gst_navseek_sink_event);
  gstbasetrans_class->transform_ip =
      GST_DEBUG_FUNCPTR (gst_navseek_transform_ip);
  gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_navseek_start);
  gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_navseek_stop);
}

static void
gst_navseek_init (GstNavSeek * navseek)
{
  gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (navseek), TRUE);

  navseek->seek_offset = 5.0;
  navseek->loop = FALSE;
  navseek->grab_seg_start = FALSE;
  navseek->grab_seg_end = FALSE;
  navseek->segment_start = GST_CLOCK_TIME_NONE;
  navseek->segment_end = GST_CLOCK_TIME_NONE;
}

static void
gst_navseek_seek (GstNavSeek * navseek, gint64 offset)
{
  gboolean ret;
  GstPad *peer_pad;
  gint64 peer_value;

  /* Query for the current time then attempt to set to time + offset */
  peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
  ret = gst_pad_query_position (peer_pad, GST_FORMAT_TIME, &peer_value);

  if (ret) {
    GstEvent *event;

    peer_value += offset;
    if (peer_value < 0)
      peer_value = 0;

    event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
        GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
        GST_SEEK_TYPE_SET, peer_value, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);

    gst_pad_send_event (peer_pad, event);
  }

  gst_object_unref (peer_pad);
}

static void
gst_navseek_change_playback_rate (GstNavSeek * navseek, gdouble rate)
{
  gboolean ret;
  GstPad *peer_pad;
  gint64 current_position;

  peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
  ret = gst_pad_query_position (peer_pad, GST_FORMAT_TIME, &current_position);

  if (ret) {
    GstEvent *event;
    gint64 start;
    gint64 stop;

    if (rate > 0.0) {
      start = current_position;
      stop = -1;
    } else {
      /* negative rate: we play from stop to start */
      start = 0;
      stop = current_position;
    }

    event = gst_event_new_seek (rate, GST_FORMAT_TIME,
        GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP,
        GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_SET, stop);

    gst_pad_send_event (peer_pad, event);
  }
}

static void
gst_navseek_segseek (GstNavSeek * navseek)
{
  GstEvent *event;
  GstPad *peer_pad;

  if ((navseek->segment_start == GST_CLOCK_TIME_NONE) ||
      (navseek->segment_end == GST_CLOCK_TIME_NONE) ||
      (!GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad))) {
    return;
  }

  if (navseek->loop) {
    event =
        gst_event_new_seek (1.0, GST_FORMAT_TIME,
        GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT,
        GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET,
        navseek->segment_end);
  } else {
    event =
        gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE,
        GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET,
        navseek->segment_end);
  }

  peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
  gst_pad_send_event (peer_pad, event);
  gst_object_unref (peer_pad);
}

static void
gst_navseek_toggle_play_pause (GstNavSeek * navseek)
{
  GstStateChangeReturn sret;
  GstState current, pending, state;

  sret = gst_element_get_state (GST_ELEMENT (navseek), &current, &pending, 0);
  if (sret == GST_STATE_CHANGE_FAILURE)
    return;

  state = (pending != GST_STATE_VOID_PENDING) ? pending : current;

  gst_element_post_message (GST_ELEMENT (navseek),
      gst_message_new_request_state (GST_OBJECT (navseek),
          (state == GST_STATE_PLAYING) ? GST_STATE_PAUSED : GST_STATE_PLAYING));
}

static gboolean
gst_navseek_src_event (GstBaseTransform * trans, GstEvent * event)
{
  GstNavSeek *navseek;
  gboolean ret = TRUE;

  navseek = GST_NAVSEEK (trans);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NAVIGATION:
    {
      /* Check for a keyup and convert left/right to a seek event */
      const GstStructure *structure;
      const gchar *event_type;

      structure = gst_event_get_structure (event);
      g_return_val_if_fail (structure != NULL, FALSE);

      event_type = gst_structure_get_string (structure, "event");
      g_return_val_if_fail (event_type != NULL, FALSE);

      if (strcmp (event_type, "key-press") == 0) {
        const gchar *key;

        key = gst_structure_get_string (structure, "key");
        g_return_val_if_fail (key != NULL, FALSE);

        if (strcmp (key, "Left") == 0) {
          /* Seek backward by 5 secs */
          gst_navseek_seek (navseek, -1.0 * navseek->seek_offset * GST_SECOND);
        } else if (strcmp (key, "Right") == 0) {
          /* Seek forward */
          gst_navseek_seek (navseek, navseek->seek_offset * GST_SECOND);
        } else if (strcmp (key, "s") == 0) {
          /* Grab the next frame as the start frame of a segment */
          navseek->grab_seg_start = TRUE;
        } else if (strcmp (key, "e") == 0) {
          /* Grab the next frame as the end frame of a segment */
          navseek->grab_seg_end = TRUE;
        } else if (strcmp (key, "l") == 0) {
          /* Toggle the loop flag. If we have both start and end segment times send a seek */
          navseek->loop = !navseek->loop;
          gst_navseek_segseek (navseek);
        } else if (strcmp (key, "f") == 0) {
          /* fast forward */
          gst_navseek_change_playback_rate (navseek, 2.0);
        } else if (strcmp (key, "r") == 0) {
          /* rewind */
          gst_navseek_change_playback_rate (navseek, -2.0);
        } else if (strcmp (key, "n") == 0) {
          /* normal speed */
          gst_navseek_change_playback_rate (navseek, 1.0);
        } else if (strcmp (key, "space") == 0) {
          gst_navseek_toggle_play_pause (navseek);
        }
      } else {
        break;
      }
      gst_event_unref (event);
      event = NULL;
      break;
    }
    default:
      break;
  }

  if (event)
    ret = GST_BASE_TRANSFORM_CLASS (parent_class)->src_event (trans, event);

  return ret;
}

static void
gst_navseek_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstNavSeek *navseek = GST_NAVSEEK (object);

  switch (prop_id) {
    case ARG_SEEKOFFSET:
      GST_OBJECT_LOCK (navseek);
      navseek->seek_offset = g_value_get_double (value);
      GST_OBJECT_UNLOCK (navseek);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_navseek_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstNavSeek *navseek = GST_NAVSEEK (object);

  switch (prop_id) {
    case ARG_SEEKOFFSET:
      GST_OBJECT_LOCK (navseek);
      g_value_set_double (value, navseek->seek_offset);
      GST_OBJECT_UNLOCK (navseek);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static gboolean
gst_navseek_sink_event (GstBaseTransform * trans, GstEvent * event)
{
  GstNavSeek *navseek = GST_NAVSEEK (trans);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_EOS:
      GST_OBJECT_LOCK (navseek);
      if (navseek->loop)
        gst_navseek_segseek (navseek);
      GST_OBJECT_UNLOCK (navseek);
      break;
    default:
      break;
  }
  return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
}

static GstFlowReturn
gst_navseek_transform_ip (GstBaseTransform * basetrans, GstBuffer * buf)
{
  GstNavSeek *navseek = GST_NAVSEEK (basetrans);

  GST_OBJECT_LOCK (navseek);

  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
    if (navseek->grab_seg_start) {
      navseek->segment_start = GST_BUFFER_TIMESTAMP (buf);
      navseek->segment_end = GST_CLOCK_TIME_NONE;
      navseek->grab_seg_start = FALSE;
    }

    if (navseek->grab_seg_end) {
      navseek->segment_end = GST_BUFFER_TIMESTAMP (buf);
      navseek->grab_seg_end = FALSE;
      gst_navseek_segseek (navseek);
    }
  }

  GST_OBJECT_UNLOCK (navseek);

  return GST_FLOW_OK;
}

static gboolean
gst_navseek_start (GstBaseTransform * trans)
{
  /* anything we should be doing here? */
  return TRUE;
}

static gboolean
gst_navseek_stop (GstBaseTransform * trans)
{
  /* anything we should be doing here? */
  return TRUE;
}
