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

static gboolean my_bus_func (GstBus * bus, GstMessage * message, gpointer user_data)
{
   Q_UNUSED(bus);
   Q_UNUSED(user_data);
   GstDevice *device;
   gchar *name;

   switch (GST_MESSAGE_TYPE (message)) {
     case GST_MESSAGE_DEVICE_ADDED:{
       gst_message_parse_device_added (message, &device);
       name = gst_device_get_display_name (device);
       g_print("Device added: %s\n", name);
       g_free (name);
       gst_object_unref (device);
       break; }
     case GST_MESSAGE_DEVICE_REMOVED: {
       gst_message_parse_device_removed (message, &device);
       name = gst_device_get_display_name (device);
       gchar *classes = gst_device_get_device_class (device); // Volker
       g_print("Device removed: %s  %s\n", name, classes);       // Volker
       g_free (name);
       gst_object_unref (device);
       break; }
     default:
       break;
   }

   return G_SOURCE_CONTINUE;
}


static gchar *get_launch_line (GstDevice * device)
{
  static const char *const ignored_propnames[] = { "name", "parent", "direction", "template", "caps", NULL };
  GString *launch_line;
  GstElement *element;
  GstElement *pureelement;
  GParamSpec **properties, *property;
  GValue value = G_VALUE_INIT;
  GValue pvalue = G_VALUE_INIT;
  guint i, number_of_properties;
  GstElementFactory *factory;

  element = gst_device_create_element (device, NULL);

  if (!element)
    return NULL;

  factory = gst_element_get_factory (element);
  if (!factory)
  {
    gst_object_unref (element);
    return NULL;
  }

  if (!gst_plugin_feature_get_name (factory))
  {
    gst_object_unref (element);
    return NULL;
  }

  launch_line = g_string_new (gst_plugin_feature_get_name (factory));

  pureelement = gst_element_factory_create (factory, NULL);

  /* get paramspecs and show non-default properties */
  properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (element), &number_of_properties);
  if (properties)
  {
    for (i = 0; i < number_of_properties; i++)
    {
      //g_print( "1111111111111111111111 %i\n", i );
      gint j;
      gboolean ignore = FALSE;
      property = properties[i];

      /* skip some properties */
      if ((property->flags & G_PARAM_READWRITE) != G_PARAM_READWRITE)
        continue;

      for (j = 0; ignored_propnames[j]; j++)
        if (!g_strcmp0 (ignored_propnames[j], property->name))
          ignore = TRUE;

      if (ignore)
        continue;

      /* Can't use _param_value_defaults () because sub-classes modify the
       * values already.
       */

      g_value_init (&value, property->value_type);
      g_value_init (&pvalue, property->value_type);
      g_object_get_property (G_OBJECT (element), property->name, &value);
      g_object_get_property (G_OBJECT (pureelement), property->name, &pvalue);
      if (gst_value_compare (&value, &pvalue) != GST_VALUE_EQUAL)
      {
        gchar *valuestr = gst_value_serialize (&value);
        if (!valuestr)
        {
          GST_WARNING ("Could not serialize property %s:%s", GST_OBJECT_NAME (element), property->name);
          g_free (valuestr);
          goto next;
        }

        g_string_append_printf (launch_line, " %s=%s", property->name, valuestr);
        g_free (valuestr);
      }

    next:
      g_value_unset (&value);
      g_value_unset (&pvalue);
    }
    g_free (properties);
  }

  gst_object_unref (element);
  gst_object_unref (pureelement);

  return g_string_free (launch_line, FALSE);
}


// GstDeviceMonitor *setup_raw_video_source_device_monitor()
void MainWindow::setup_raw_video_source_device_monitor()
{
   GstDeviceMonitor *monitor;
   GstBus *bus;
   GstCaps *caps;
   GstDevice *device;

   monitor = gst_device_monitor_new ();

   bus = gst_device_monitor_get_bus (monitor);
   gst_bus_add_watch (bus, my_bus_func, NULL);
   gst_object_unref (bus);

   caps = gst_caps_new_empty_simple ("audio/x-raw");
   gst_device_monitor_add_filter (monitor, "Audio/Source", caps);

   gchar *name;
   GList *iterator = NULL;
   GList *list = gst_device_monitor_get_devices( monitor );
   for ( iterator = list; iterator; iterator = iterator->next )
   {
       device = (GstDevice*)iterator->data;
       name = gst_device_get_display_name( device );
       g_print("%s   %s\n", get_launch_line( device ), name );
   }

   gst_caps_unref (caps);

   // pacmd list-sources
   // Der Audioname steht in den Properties
   // https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gstreamer-GstDevice.html#gst-device-get-properties
   // https://github.com/GStreamer/gst-plugins-base/blob/master/tools/gst-device-monitor.c


   gst_device_monitor_start (monitor);

   //return monitor;
}


void cb_fps_measurements(GstElement *fpsdisplaysink,
                         gdouble arg0,
                         gdouble arg1,
                         gdouble arg2,
                         gpointer user_data)
{
       g_print("dropped: %.0f, current: %.2f, average: %.2f\n", arg1, arg0, arg2);
}


#include <QStyleFactory>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    setup_raw_video_source_device_monitor();
