/* based on: input-selector-test.c
 * GStreamer
 * Copyright (C) 2003 Julien Moutte <julien@moutte.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>


#include <gst/gst.h>

static GMainLoop *loop = NULL;

static gboolean
my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
{
  g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));

  switch (GST_MESSAGE_TYPE (message)) {
    case GST_MESSAGE_ERROR:{
      GError *err;
      gchar *debug;

      gst_message_parse_error (message, &err, &debug);
      g_print ("Error: %s\n", err->message);
      g_error_free (err);
      g_free (debug);

      g_main_loop_quit (loop);
      break;
    }
    case GST_MESSAGE_EOS:
      /* end-of-stream */
      g_main_loop_quit (loop);
      break;
    default:
      /* unhandled message */
      break;
  }

  /* we want to be notified again the next time there is a message
   * on the bus, so returning TRUE (FALSE means we want to stop watching
   * for messages on the bus and our callback should not be called again)
   */
  return TRUE;
}



static gboolean
switch_timer (GstElement * audio_switch)
{
  gint nb_sources;
  GstPad *active_pad, *new_pad;
  gchar *active_name;

  g_message ("switching");
  g_object_get (G_OBJECT (audio_switch), "n-pads", &nb_sources, NULL);
  g_object_get (G_OBJECT (audio_switch), "active-pad", &active_pad, NULL);

  active_name = gst_pad_get_name (active_pad);
  if (strcmp (active_name, "sink_0") == 0) {
    new_pad = gst_element_get_static_pad (audio_switch, "sink_1");
  } else {
    new_pad = gst_element_get_static_pad (audio_switch, "sink_0");
  }
  g_object_set (G_OBJECT (audio_switch), "active-pad", new_pad, NULL);
  g_free (active_name);
  gst_object_unref (new_pad);

  g_message ("current number of sources : %d, active source %s",
      nb_sources, gst_pad_get_name (active_pad));

  return FALSE; // stop periodic timer
  return (GST_STATE (GST_ELEMENT (audio_switch)) == GST_STATE_PLAYING);
}


static void
pad_added_cb (GstElement * deinterleave, GstPad * new_pad, GstElement * inputselector)
{
    gchar* name;
    GstPadLinkReturn lres;
    GstPad *sinkpad = NULL;

    name = gst_pad_get_name(new_pad);

    // create a request pad on input-selector...
    if (g_str_has_prefix(name, "src_0")) {
        sinkpad = gst_element_get_request_pad(inputselector, "sink_0");
    }
    else if (g_str_has_prefix(name, "src_1")) {
        sinkpad = gst_element_get_request_pad(inputselector, "sink_1");
    }

    // ... and link deinterleave.src to input-selector.sink
    lres = gst_pad_link(new_pad, sinkpad);
    g_assert(lres == GST_PAD_LINK_OK);
    g_message ("linked deinterleave %s to inputselector", name);

    g_free(name);

    return;
}

int
main (int argc, char *argv[])
{
  GstElement *pipeline, *audio_src, *deinterleave, *audio_switch, *audio_convert, *audio_sink;
  GstElement *capsfilter;
  GstBus *bus;

  /* Initing GStreamer library */
  gst_init (&argc, &argv);

  loop = g_main_loop_new (NULL, FALSE);

  pipeline = gst_pipeline_new ("pipeline");
  audio_src = gst_element_factory_make ("alsasrc", "audio_src");
  //g_object_set(audio_src, "device", "dsnooped", NULL);
  //g_object_set(audio_src, "device", "hw:0,0", NULL);

  capsfilter = gst_element_factory_make ("capsfilter", "caps0");
  g_object_set (G_OBJECT (capsfilter), "caps",
      gst_caps_from_string ("audio/x-raw,format=S16LE,rate=48000,channels=2"), NULL);
  deinterleave = gst_element_factory_make ("deinterleave", "deinterleave");
  audio_switch = gst_element_factory_make ("input-selector", "audio_switch");
  g_object_set (audio_switch, "sync-streams", FALSE, NULL);

  g_signal_connect (deinterleave, "pad-added", G_CALLBACK (pad_added_cb), audio_switch);
  audio_convert = gst_element_factory_make ("audioconvert", "audio_convert");
  audio_sink = gst_element_factory_make ("alsasink", "audio_sink");
  g_object_set (G_OBJECT (audio_sink), "sync", FALSE, NULL);
  //g_object_set(audio_sink, "device", "dmixed", NULL);
  //g_object_set(audio_sink, "device", "hw:0,0", NULL);

  if (!pipeline || !audio_src || !deinterleave || !audio_switch || !audio_convert || !audio_sink || !capsfilter)
  {
    g_message ("missing element\n");
    return -1;
  }

  gst_bin_add_many (GST_BIN (pipeline), audio_src, deinterleave, audio_switch,
      audio_convert, audio_sink, capsfilter, NULL);

  gst_element_link_many (audio_src, capsfilter, deinterleave, NULL);
  gst_element_link_many (audio_switch, audio_convert, audio_sink, NULL);

  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  gst_bus_add_watch (bus, my_bus_callback, NULL);
  gst_object_unref (bus);
  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);

  g_timeout_add (5000, (GSourceFunc) switch_timer, audio_switch);

  g_main_loop_run (loop);

  gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);

  /* unref */
  gst_object_unref (GST_OBJECT (pipeline));

  exit (0);
}
