#include <gst/gst.h>
#include <glib.h>
#include <stdio.h>
#include <pthread.h>

GMainLoop *loop;

//callback function

gboolean TickCallback(GstClock *clock,GstClockTime time,GstClockID id,gpointer user_data) {

gst_clock_id_unref(id);
g_message("Inside callback function TickCallback ");
return FALSE;

}


static gboolean bus_call (GstBus *bus,GstMessage *msg,gpointer    data)
{
  GMainLoop *loop = (GMainLoop *) data;
  switch (GST_MESSAGE_TYPE (msg)) {

    case GST_MESSAGE_EOS:
      g_print ("End of stream\n");
      //gst_element_set_state (pipeline, GST_STATE_NULL);
      g_main_loop_quit (loop);
      break;
    case GST_MESSAGE_ERROR: {
      gchar *debug;
      GError *error;
      gst_message_parse_error (msg, &error, &debug);
      g_free (debug);
      g_printerr ("Error: %s\n", error->message);
      g_error_free (error);
      g_main_loop_quit (loop);
      break;
    }
    


   default:
      break;
  }
  return TRUE;
}

static void on_pad_added (GstElement *element,GstPad *pad,gpointer data)
{
  GstPad *sinkpad;
  GstElement *decoder = (GstElement *) data;
  /* We can now link this pad with the vorbis-decoder sink pad */
  g_print ("Dynamic pad created, linking demuxer/decoder\n");
  sinkpad = gst_element_get_static_pad (decoder, "sink");
  gst_pad_link (pad, sinkpad);
  gst_object_unref (sinkpad);
}

void  start_routine()
{
	
	//if(loop!=NULL)
		g_main_loop_run(loop);
}


void pause(GstElement *pipeline)
{


	if( GST_STATE(pipeline) == GST_STATE_PLAYING)
	{
		g_message("Currently in playing state");
		
                GstClockID id;
	        GstClockTime start_time=900000000;
	        GstClockTime interval=9000000000;
	        GstClockReturn ClockResult;
                id=gst_clock_new_periodic_id(pipeline->clock,start_time,interval);
		if(id)
		{
			g_message("id created=%d",(int )id);
	    		ClockResult=gst_clock_id_wait_async(id,(GstClockCallback *)TickCallback,"Tick sending");
		}
		else
			g_message("id is not created\n");

		gst_element_set_state(pipeline,GST_STATE_PAUSED);
	}
	else if( GST_STATE(pipeline) == GST_STATE_PAUSED )
	{
		g_message("Currently in paused state,");
		gst_element_set_state(pipeline,GST_STATE_PLAYING);
	}
}


gint main(gint argc,gchar *argv[])
{
  int choice;
  GstElement *pipeline, *source, *demuxer, *decoder, *conv, *sink, *audiosink ,*audiodecoder;
  GstBus *bus;
  pthread_t thread;
  /* Initialisation */
  gst_init (&argc, &argv);
  loop = g_main_loop_new (NULL, FALSE);
  /* Check input arguments */
  if (argc != 2) {
    g_printerr ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]);
    return -1;
  }
  /* Create gstreamer elements */
  pipeline = gst_pipeline_new ("video-player");
  source   = gst_element_factory_make ("filesrc",       "file-source");
  demuxer = gst_element_factory_make ("qtdemux",  "mp4-demuxer");
  decoder = gst_element_factory_make ("ffdec_mpeg4",      "mpeg4-decoder");
  conv     = gst_element_factory_make ("ffenc_mpeg4",  "converter");
  sink     = gst_element_factory_make ("xvimagesink", "video-output");
  audiodecoder = gst_element_factory_make ("faad",      "aac-decoder");
  audiosink     = gst_element_factory_make ("alsasink", "audio-output");
  //g_object_set(G_OBJECT(sink),"location","sreerenj.mp4",NULL);
  if (!pipeline || !source || !demuxer || !decoder || !conv || !sink || !audiodecoder ||  !audiosink) {
    g_printerr ("One element could not be created. Exiting.\n");
    return -1;
  }



  /* Set up the pipeline */
  /* we set the input filename to the source element */
  g_object_set (G_OBJECT (source), "location", argv[1], NULL);
  /* we add a message handler */
  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  gst_bus_add_watch (bus, bus_call, loop);
  gst_object_unref (bus);
  /* we add all elements into the pipeline */
  /* file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output */
  gst_bin_add_many (GST_BIN (pipeline),
                    source, demuxer, decoder, conv, sink, NULL);
  /* we link the elements together */
  /* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output */
  gst_element_link (source, demuxer);
  gst_element_link_many (decoder,sink, NULL);
  g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder);
  /* note that the demuxer will be linked to the decoder dynamically.
     The reason is that Ogg may contain various streams (for example
     audio and video). The source pad(s) will be created at run time,
     by the demuxer when it detects the amount and nature of streams.
     Therefore we connect a callback function which will be executed
     when the "pad-added" is emitted.*/
  /* Set the pipeline to "playing" state*/
  g_print ("Now playing: %s\n", argv[1]);

                                                       
                                                        



  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  


   g_print ("Running...\n");


	printf("Enter your choice 1: for pause and play  \n");
	pthread_create(&thread,NULL,(void *)start_routine,NULL);
	while(1)
	{
		scanf("%d",&choice);
		switch(choice)
		{
			case 1:pause(pipeline);	
			       break;
			default : exit(0);break;
		}
	}




 
  /* Out of the main loop, clean up nicely */
  g_print ("Returned, stopping playback\n");
  gst_element_set_state (pipeline, GST_STATE_NULL);
  

  g_print ("Deleting pipeline\n");
  gst_object_unref (GST_OBJECT (pipeline));
  return 0;
}




