/* $Id$
 * test caps negotiation in gst
 *
 * gcc -Wall -g `pkg-config gstreamer-0.10 --cflags --libs` negotiate.c -o negotiate
 *
 * clear;GST_DEBUG="default:3,GST_PADS:3" ./negotiate
 * clear;GST_DEBUG="default:4,tee:3" ./negotiate 
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <gst/gst.h>

#define SINK_NAME "alsasink"
#define ELEM_NAME "volume"
#define SRC_NAME "audiotestsrc"

static GMainLoop *main_loop=NULL;

static void message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) {
  const GstStructure *s;

  s = gst_message_get_structure (message);
  g_print ("message from \"%s\" (%s): ",
      GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))),
      gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
  if (s) {
    gchar *sstr;

    sstr = gst_structure_to_string (s);
    printf ("%s\n", sstr);
    g_free (sstr);
  }
  else {
    printf ("no message details\n");
  }
}

static void eos_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) {
  g_main_loop_quit(main_loop);
}

static void state_changed(const GstBus * const bus, GstMessage *message, GstPipeline * pipeline) {
  if(GST_MESSAGE_SRC(message) == GST_OBJECT(pipeline)) {
    GstState oldstate,newstate,pending;

    gst_message_parse_state_changed(message,&oldstate,&newstate,&pending);
    switch(GST_STATE_TRANSITION(oldstate,newstate)) {
      case GST_STATE_CHANGE_NULL_TO_READY:
        GST_INFO("ready ===========================================================");
        break;
      case GST_STATE_CHANGE_READY_TO_PAUSED:
        GST_INFO("paused ==========================================================");
        break;
      case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
        GST_INFO("playing =========================================================");
        break;
      default:
        break;
    }
  }
}


int main(int argc, char **argv) {
  GstElement *bin;
  /* elements used in pipeline */
  GstElement *sink, *mix;
  GstElement *proc1,*proc2;
  GstElement *queue1, *queue2;
  GstElement *src, *tee;
  GstBus *bus;
  
  /* init gstreamer */
  gst_init(&argc, &argv);
  g_log_set_always_fatal(G_LOG_LEVEL_WARNING);
  
  /* create a new bin to hold the elements */
  bin = gst_pipeline_new ("song");
 
  /* make elements */
  if(!(sink = gst_element_factory_make (SINK_NAME, "sink"))) {
    fprintf(stderr,"Can't create element \""SINK_NAME"\"\n");exit (-1);
  }
  if(!(mix = gst_element_factory_make ("adder", "mix"))) {
    fprintf(stderr,"Can't create element \"adder\"\n");exit (-1);
  }
  if(!(proc1 = gst_element_factory_make (ELEM_NAME, "proc1"))) {
    fprintf(stderr,"Can't create element \""ELEM_NAME"\"\n");exit (-1);
  }
  if(!(proc2 = gst_element_factory_make (ELEM_NAME, "proc2"))) {
    fprintf(stderr,"Can't create element \""ELEM_NAME"\"\n");exit (-1);
  }
  if(!(queue1 = gst_element_factory_make ("queue", "queue1"))) {
    fprintf(stderr,"Can't create element \"queue\"\n");exit (-1);
  }
  if(!(queue2 = gst_element_factory_make ("queue", "queue2"))) {
    fprintf(stderr,"Can't create element \"queue\"\n");exit (-1);
  }
  if(!(tee = gst_element_factory_make ("tee", "tee"))) {
    fprintf(stderr,"Can't create element \"tee\"\n");exit (-1);
  }
  if(!(src = gst_element_factory_make (SRC_NAME, "src"))) {
    fprintf(stderr,"Can't create element \""SRC_NAME"\"\n");exit (-1);
  }
  g_object_set(src, "num-buffers",25, "volume",(gdouble)0.5, NULL);
    
  /* add objects to the main bin */
  gst_bin_add_many (GST_BIN (bin), src, tee, queue1, queue2, proc1, proc2, mix, sink, NULL);
  
  /* link chain1 */
  if(!gst_element_link_many (src, tee, queue1, proc1, mix, sink, NULL)) {
    fprintf(stderr,"Can't link chain 1\n");exit (-1);
  }
	
  /* now link chain2 */
  if(!gst_element_link_many (tee, queue2, proc2, mix, NULL)) {
    fprintf(stderr,"Can't link chain2\n");exit (-1);
  }

  /* see if we get errors */
  bus = gst_pipeline_get_bus (GST_PIPELINE (bin));
  gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
  g_signal_connect (bus, "message::error", G_CALLBACK(message_received), bin);
  g_signal_connect (bus, "message::warning", G_CALLBACK(message_received), bin);
  g_signal_connect (bus, "message::eos", G_CALLBACK(eos_received), bin);
  g_signal_connect (bus, "message::state-changed", G_CALLBACK(state_changed), bin);
  gst_object_unref (GST_OBJECT (bus));
  
  main_loop=g_main_loop_new(NULL,FALSE);
	
  /* start playing */
  if(gst_element_set_state (bin, GST_STATE_PLAYING)==GST_STATE_CHANGE_FAILURE) {
    fprintf(stderr,"Can't start playing\n");exit(-1);
  }

  g_main_loop_run(main_loop);

  gst_element_set_state (bin, GST_STATE_NULL);
  
  /* we don't need a reference to these objects anymore */
  gst_object_unref (GST_OBJECT (bin));

  exit (0);
}
