/***************************************************************************
 *   Copyright (C) 2009 by Fraxinas   *
 *   andreas.frisch@multimedia-labs.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

// gcc -Wall -g `pkg-config gstreamer-0.10 --cflags --libs` hls_latency.c -ohls_latency

#include <gst/gst.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/video.h>
#include <fcntl.h>
#include <string.h>
#include <glib.h>
#include <glib/gprintf.h>
// #include <mcheck.h>

GST_DEBUG_CATEGORY (hls_latency_debug);
#define GST_CAT_DEFAULT hls_latency_debug

typedef struct _App App;

struct _App
{
	GstElement *playbin;
	GMainLoop *loop;
	gint fragments_cache;
};

App s_app;

static gboolean bus_message (GstBus * bus, GstMessage * message, App * app)
{
  GstObject *source;
  gchar *string;

  if (!message)
    return FALSE;
  source = GST_MESSAGE_SRC (message);
  if (!GST_IS_OBJECT (source))
    return FALSE;

  if (gst_message_get_structure (message))
    string = gst_structure_to_string (gst_message_get_structure (message));
  else
    string = g_strdup (GST_MESSAGE_TYPE_NAME (message));
#if 0
  gchar *sourceName = gst_object_get_name (source);
  g_print ("gst_message from %s: %s\n", sourceName, string);
#endif
  g_free (string);

	switch (GST_MESSAGE_TYPE (message)) {
		case GST_MESSAGE_ERROR:
		{
			GError *gerror;
			gchar *debug;
			
			gst_message_parse_error (message, &gerror, &debug);
			gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
			g_error_free (gerror);
			g_free (debug);
			
			g_main_loop_quit (app->loop);
			break;
		}
		case GST_MESSAGE_WARNING:
		{
			GError *gerror;
			gchar *debug;
			
			gst_message_parse_warning (message, &gerror, &debug);
			gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
			g_error_free (gerror);
			g_free (debug);
			
			//       g_main_loop_quit (app->loop);
			break;
		}
		case GST_MESSAGE_EOS:
			g_message ("received EOS");
			g_main_loop_quit (app->loop);
			break;
		case GST_MESSAGE_STATE_CHANGED:
		{
			GstState old_state, new_state;
			gst_message_parse_state_changed(message, &old_state, &new_state, NULL);
		
			GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state);
			
			GstElement *hlsdemux = gst_bin_get_by_name(GST_BIN(app->playbin), "hlsdemux0");

			if (hlsdemux && GST_MESSAGE_SRC(message) == GST_OBJECT(hlsdemux))
			{
				GST_DEBUG("hlsdemux0@%p,GST_MESSAGE_SRC(message)@%p  %s -> %s", GST_OBJECT(hlsdemux),GST_MESSAGE_SRC(message),gst_element_state_get_name(old_state), gst_element_state_get_name(new_state));
				if (transition == GST_STATE_CHANGE_READY_TO_PAUSED)
				{
					g_object_set (G_OBJECT (hlsdemux), "fragments-cache", app->fragments_cache, NULL);
					gint i;
					g_object_get (G_OBJECT (hlsdemux), "fragments-cache", &i, NULL);
					GST_DEBUG("hlsdemux property set! == %i",i);
				}
				gst_object_unref(hlsdemux);
			}
			break;
		}
		default:
			break;
	}
  return TRUE;
}

int main (int argc, char *argv[])
{
	App *app = &s_app;
	GstBus *bus;
	const gchar *nano_str;
	guint major, minor, micro, nano;
	gst_init (&argc, &argv);
	
	GST_DEBUG_CATEGORY_INIT (hls_latency_debug, "HLS_LATENCY", GST_DEBUG_BOLD|GST_DEBUG_FG_YELLOW|GST_DEBUG_BG_BLUE, "hlsdemux latency testcase");
	
	if (argc < 3) {
		g_print ("usage: %s <uri> <fragments-cache>\n", argv[0]);
		return -1;
	}

	app->fragments_cache=atoi(argv[2]);

	gst_version (&major, &minor, &micro, &nano);
	
	if (nano == 1)
		nano_str = "(CVS)";
	else if (nano == 2)
		nano_str = "(Prerelease)";
	else
		nano_str = "";
	
	GST_DEBUG ("%s is linked against GStreamer %d.%d.%d %s for dreambox 8000\n",
      argv[0], major, minor, micro, nano_str);

	/* create a mainloop to get messages */
	app->loop = g_main_loop_new (NULL, TRUE);
	
	app->playbin = gst_element_factory_make ("playbin2", NULL);
	g_assert (app->playbin);

	bus = gst_pipeline_get_bus (GST_PIPELINE (app->playbin));

	/* add watch for messages */
	gst_bus_add_watch (bus, (GstBusFunc) bus_message, app);

	/* set to read from given uri */
	g_object_set (app->playbin, "uri", argv[1], NULL);

	/* go to playing and wait in a mainloop. */
// 	mtrace();
	gst_element_set_state (app->playbin, GST_STATE_PLAYING);
	
	/* this mainloop is stopped when we receive an error or EOS */
	g_main_loop_run (app->loop);
	
	g_message ("stopping");
	
	gst_element_set_state (app->playbin, GST_STATE_NULL);
	
	gst_object_unref (bus);
	g_main_loop_unref (app->loop);
// 	muntrace();
	return 0;
}

