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

GstElement *_pipeline, *_fakesink, *_remotesink, *_mpoint, *_videobin, *_pipe, *gdppay;

void create_pipeline_bin()
{
        GstElement *tee, *queue1, *queue2, *valve, *xvimagesink, *audiosink;

	_pipeline      = gst_element_factory_make("playbin",  NULL);

	tee			= gst_element_factory_make("tee",  NULL);
        xvimagesink   = gst_element_factory_make("ximagesink", NULL);

        GstPad* pad;

	_videobin = gst_bin_new("videobin");
        queue1			= gst_element_factory_make("queue", NULL);
        queue2			= gst_element_factory_make("queue", NULL);
        valve                   = gst_element_factory_make("valve", NULL);

	_fakesink		= gst_element_factory_make("fakesink", NULL);
        audiosink               = gst_element_factory_make("fakesink", NULL);

	gst_object_ref(_fakesink);

        _mpoint = valve;

        gst_bin_add_many(GST_BIN(_videobin), tee, queue1, queue2, valve, xvimagesink, _fakesink, NULL);

        gst_element_link_many(tee, queue1, xvimagesink, NULL);
        gst_element_link_many(tee, queue2, valve, _fakesink, NULL);
	pad = gst_element_get_static_pad (tee, "sink");
	gst_element_add_pad (_videobin, gst_ghost_pad_new ("sink", pad));
	gst_object_unref (GST_OBJECT (pad));

        g_object_set(G_OBJECT (_pipeline), "uri", "file:///home/ray/test.mp4", NULL);
        g_object_set(G_OBJECT (_pipeline), "video-sink", _videobin, NULL);
        g_object_set(G_OBJECT (_pipeline), "audio-sink", audiosink, NULL);

        bus = gst_pipeline_get_bus (GST_PIPELINE (_pipeline));
        gst_bus_add_watch (bus, bus_call, NULL);
        gst_object_unref (bus);

	gst_element_set_state (_pipeline, GST_STATE_PLAYING);
}

void create_gdp_bin()
{
        GstElement *gdppay;
        GstPad* pad;

        gdppay		= gst_element_factory_make("gdppay",  NULL);
        _pipe		= gst_element_factory_make("filesink",  NULL);

        g_object_set(G_OBJECT (_pipe), "location", "/usr/local/share/workspace/playground/work/test.gdp", NULL);

        _remotesink = gst_bin_new("gdpbin");
        gst_bin_add_many(GST_BIN(_remotesink), gdppay, _pipe, NULL);
        gst_element_link_many(gdppay, _pipe, NULL);
        pad = gst_element_get_static_pad (gdppay, "sink");
        gst_element_add_pad (_remotesink, gst_ghost_pad_new ("sink", pad));
        gst_object_unref (GST_OBJECT (pad));
}

void create_avi_bin()
{
        GstElement *jpegenc, *avimux;
        GstPad* pad;

        jpegenc		= gst_element_factory_make("jpegenc",  NULL);
        avimux          = gst_element_factory_make("avimux",  NULL);
        _pipe		= gst_element_factory_make("filesink",  NULL);

        g_object_set(G_OBJECT (_pipe), "location", "/usr/local/share/workspace/playground/work/test.gdp", NULL);

        _remotesink = gst_bin_new("gdpbin");
        gst_bin_add_many(GST_BIN(_remotesink), jpegenc, avimux, _pipe, NULL);
        gst_element_link_many(jpegenc, avimux, _pipe, NULL);
        pad = gst_element_get_static_pad (jpegenc, "sink");
        gst_element_add_pad (_remotesink, gst_ghost_pad_new ("sink", pad));
        gst_object_unref (GST_OBJECT (pad));
}

void create_xsink_bin()
{
        GstElement *testxsink;
        GstPad* pad;

        testxsink	= gst_element_factory_make("ximagesink",  NULL);

        _remotesink = gst_bin_new("gdpbin");
        gst_bin_add_many(GST_BIN(_remotesink), testxsink, NULL);
        pad = gst_element_get_static_pad (testxsink, "sink");
        gst_element_add_pad (_remotesink, gst_ghost_pad_new ("sink", pad));
        gst_object_unref (GST_OBJECT (pad));
}

void connect_remote_client()
{
	if (_remotesink && _mpoint && _videobin)
	{
                g_object_set(G_OBJECT (_mpoint), "drop", TRUE, NULL);
		gst_element_unlink(_mpoint, _fakesink);
		gst_bin_remove(GST_BIN(_videobin), _fakesink);
		gst_element_set_state (_fakesink, GST_STATE_NULL);
		gst_bin_add(GST_BIN(_videobin), _remotesink);
		gst_element_link(_mpoint, _remotesink);

                gst_element_sync_state_with_parent(_remotesink);
                gst_element_set_state (_pipeline, GST_STATE_PLAYING);

                g_object_set(G_OBJECT (_mpoint), "drop", FALSE, NULL);
	}
}

gboolean connect_callback(gpointer)
{
	qDebug()<<"callback called";
	connect_remote_client();
	return FALSE;
}

int main(int argc, char *argv[])
{
	GMainLoop *loop;
    
        gst_debug_set_active(true);
        gst_debug_set_default_threshold(GST_LEVEL_WARNING);

        create_gdp_bin();
//        create_avi_bin();
//        create_xsink_bin();
        create_pipeline_bin();

        g_timeout_add(7000, connect_callback, NULL);
	
	g_main_loop_run (loop);
}
