/*
 * =====================================================================================
 *
 *       Filename:  bug.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  08/14/2014 11:44:39 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:   (), |wangxinyu@chison.com.cn|
 *   Organization:  
 *
 * =====================================================================================
 */
#include <glib.h>
#include <gst/gst.h>
#include <gst/gstelement.h>
#include <gst/gstpad.h>
#include <gst/gstparse.h>

#include <assert.h>


static GstPad *blockpad;
static GstBin *pipeline;
static GstElement *combiner;
static GstElement *prevsrc;
static GMainLoop *loop;

static int allow_patterns[4]={0,1,12,18};

static int pattern_counter=0;

static void setSinkPad(GstElement* ele){

    GstPad *src=gst_element_get_static_pad(ele,"src");

    GstPad *sinkPad=gst_pad_get_peer(src);

    assert(sinkPad);

    g_object_set(G_OBJECT(sinkPad),
            "xpos",0,"ypos",0,
            "width",400,"height",400,NULL);
}

static
void changePipeline(){

  GstElement *next = gst_element_factory_make("videotestsrc", "to_change");

  g_print ("Switching from '%s' to '%s'..\n", GST_OBJECT_NAME (prevsrc),
      GST_OBJECT_NAME (next));

  gst_element_set_state (prevsrc, GST_STATE_NULL);

  GstStateChangeReturn waiting=gst_element_get_state(
          prevsrc,NULL,NULL,GST_CLOCK_TIME_NONE);

  GstPad *old_request_pad=gst_pad_get_peer(
          gst_element_get_static_pad(prevsrc,"src"));

  assert(old_request_pad);

  pattern_counter=(pattern_counter+1)%4;

  g_object_set(G_OBJECT(next),"pattern",allow_patterns[pattern_counter],NULL);

  /* remove unlinks automatically */
  GST_DEBUG_OBJECT (pipeline, "removing %" GST_PTR_FORMAT, prevsrc);
  gst_bin_remove (GST_BIN (pipeline), prevsrc);


  gst_element_release_request_pad(combiner,old_request_pad);

  GST_DEBUG_OBJECT (pipeline, "adding   %" GST_PTR_FORMAT, next);
  gst_bin_add (GST_BIN (pipeline), next);

  GST_DEBUG_OBJECT (pipeline, "linking..");


  GstPad* new_request_pad=gst_element_get_request_pad(combiner,"sink_%u");

  blockpad=gst_element_get_static_pad(next,"src");

  gst_pad_link(blockpad,new_request_pad);

  setSinkPad(next);

  gst_element_set_state (next, GST_STATE_PLAYING);

  GST_DEBUG_OBJECT (pipeline, "done");

  prevsrc=next;

}



static gboolean
timeout_cb (gpointer user_data)
{
    changePipeline();

  g_timeout_add_seconds (4, timeout_cb, NULL);

  return FALSE;
}


int
main (int argc, char **argv)
{


    gst_init(NULL,NULL);

    GMainLoop *loop=g_main_loop_new(NULL,FALSE);

    pipeline=GST_PIPELINE(gst_parse_launch("videotestsrc name=to_change ! glvideomixer name=c ! "
            "glimagesink name=sink videotestsrc name=no_change ! c.",NULL));




    GstElement *sink=gst_bin_get_by_name(pipeline,"sink");

    g_object_set(G_OBJECT(sink),"qos",FALSE,NULL);

    prevsrc=gst_bin_get_by_name(pipeline,"to_change");

    setSinkPad(prevsrc);

    assert(prevsrc);

    combiner=gst_bin_get_by_name(pipeline,"c");

    assert(combiner);

    blockpad=gst_element_get_static_pad(prevsrc,"src");

    assert(blockpad);

    g_timeout_add_seconds (1, timeout_cb, NULL);


    GstElement *no_change=gst_bin_get_by_name(pipeline,"no_change");

    assert(no_change);

    GstPad* s2=gst_element_get_static_pad(no_change,"src");

    GstPad* sink2=gst_pad_get_peer(s2);

    g_object_set(G_OBJECT(sink2),
            "xpos",400,"ypos",400,
            "width",400,"height",400,NULL);

    gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);

    g_main_loop_run(loop);

    gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_NULL);

    gst_object_unref(pipeline);


    g_main_loop_unref(loop);


  return 0;
}

