
#include <gst/gst.h>

static gboolean done; /* FALSE */

static void
handoff_cb (GstElement *fakesink, GstBuffer *buf, GstPad *pad, gpointer foobar)
{
	const guint8 *data;
	guint64       off;
	guint         left;

	off = GST_BUFFER_OFFSET (buf);
	left = GST_BUFFER_SIZE (buf);
	data = GST_BUFFER_DATA (buf);

	if (!GST_BUFFER_OFFSET_IS_VALID (buf))
		off = 0;

	while (left > 0)
	{
		if (off % 16 == 0 || data == GST_BUFFER_DATA (buf))
			g_print ("\n%08" G_GINT64_MODIFIER "x ", off);

		if (data == GST_BUFFER_DATA (buf) && (off % 16) != 0)
		{
			gint i;
			g_print (" ");
			if (off % 16 > 8)
				g_print (" ");
			for (i = (off % 16); i > 0; --i)
				g_print ("   ");
			
		}

		if (off % 8 == 0)
			g_print (" ");

		g_print ("%02x ", (guint) *data);

		--left;
		++off;
		++data;
	}

	done = TRUE;
}


int
main (int argc, char **argv)
{
	GstElement *pipeline, *src, *sink;
	guint64 off;
	gint ret;

	gst_init (&argc, &argv);

	if (argc < 3)
		g_error ("Usage: %s <largefile> <offset>\n", argv[0]);

	if (g_str_has_prefix (argv[2], "0x"))
		ret = sscanf (argv[2] + 2, "%" G_GINT64_MODIFIER "x", &off);
	else
		ret = sscanf (argv[2], "%" G_GINT64_MODIFIER "u", &off);

	if (ret != 1)
		g_error ("Couldn't parse offset.\n");

	pipeline = gst_pipeline_new ("pipeline");

	src = gst_element_factory_make ("filesrc", "filesrc");
	sink = gst_element_factory_make ("fakesink", "fakesink");

	gst_bin_add (GST_BIN (pipeline), src);
	gst_bin_add (GST_BIN (pipeline), sink);

	if (!gst_element_link (src, sink))
		g_error ("link failed\n");

	g_object_set (src, "location", argv[1], NULL);

	gst_element_set_state (pipeline, GST_STATE_PAUSED);

	g_print ("Paused.\n");

	if (!gst_element_seek (sink, 1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH,
	    GST_SEEK_TYPE_CUR, off, GST_SEEK_TYPE_CUR, (guint64) -1))
	{
		g_error ("seek failed!\n");
	}

	g_print ("Seek OK.\n");

	g_signal_connect (sink, "handoff", G_CALLBACK (handoff_cb), NULL);

	g_object_set (sink, "signal-handoffs", TRUE, NULL);

	gst_element_set_state (pipeline, GST_STATE_PLAYING);

	while (!done) {
		g_usleep (G_USEC_PER_SEC/100);
	}

	return 0;
}

