
#include <glib/gi18n.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <gst/gst.h>

typedef enum
{
  MODE_IMAGE = 0,
  MODE_VIDEO
} GstCameraBinMode;

typedef enum {
  GST_CAMERABIN_FLAG_SOURCE_RESIZE               = (1 << 0),
  GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION     = (1 << 1),
  GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION = (1 << 2),
  GST_CAMERABIN_FLAG_VIEWFINDER_SCALE            = (1 << 3),
  GST_CAMERABIN_FLAG_AUDIO_CONVERSION            = (1 << 4),
  GST_CAMERABIN_FLAG_DISABLE_AUDIO               = (1 << 5),
  GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION      = (1 << 6),
  GST_CAMERABIN_FLAG_VIDEO_COLOR_CONVERSION      = (1 << 7)
} GstCameraBinFlags;


GstBus *bus;
GstElement *camerabin;

GST_DEBUG_CATEGORY (cheese_camera_cat);
#define GST_CAT_DEFAULT cheese_camera_cat

static void
cheese_camera_bus_message_cb (GstBus *bus, GstMessage *message, gpointer *data)
{
  switch (GST_MESSAGE_TYPE (message))
  {
    case GST_MESSAGE_WARNING:
    {
      GError *err = NULL;
      gchar *debug = NULL;
      gst_message_parse_warning (message, &err, &debug);

      if (err && err->message) {
        g_warning ("%s\n", err->message);
        g_error_free (err);
      } else {
        g_warning ("Unparsable GST_MESSAGE_WARNING message.\n");
      }

      g_free (debug);
      break;
    }
    case GST_MESSAGE_ERROR:
    {
      GError *err = NULL;
      gchar *debug = NULL;
      gst_message_parse_error (message, &err, &debug);

      if (err && err->message) {
        g_warning ("%s\n", err->message);
        g_error_free (err);
      } else {
        g_warning ("Unparsable GST_MESSAGE_ERROR message.\n");
      }

      g_free (debug);
      gtk_main_quit();
      break;
    }
    default:
    {
      break;
    }
  }
}

void
cheese_camera_play ()
{
  g_signal_emit_by_name (camerabin, "set-video-resolution-fps",
                         320, 240, 0, 1, 0);
  gst_element_set_state (camerabin, GST_STATE_PLAYING);
}

void
cheese_camera_stop ()
{
  if (camerabin != NULL)
    gst_element_set_state (camerabin, GST_STATE_NULL);
}

static gboolean
cheese_camera_start_video_recording (const char *filename)
{
  g_print ("Cheese! filename: testcamera.ogv\n");
  g_object_set (camerabin, "mode", MODE_VIDEO, NULL);
  g_object_set (camerabin, "filename", filename, NULL);
  g_signal_emit_by_name (camerabin, "capture-start", 0);
  return FALSE;
}

static gboolean
cheese_camera_stop_video_recording ()
{
  g_print ("stop\n");
  g_signal_emit_by_name (camerabin, "capture-stop", 0);
  g_object_set (camerabin, "mode", MODE_IMAGE, NULL);
  return FALSE;
}

static void
cheese_camera_init ()
{
  camerabin = gst_element_factory_make ("camerabin", "camerabin");
  g_object_set (camerabin, "video-capture-height", 0,
                "video-capture-width", 0, NULL);

  /* Set flags to enable conversions*/

  g_object_set (G_OBJECT (camerabin), "flags",
                GST_CAMERABIN_FLAG_AUDIO_CONVERSION |
                GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION |
                GST_CAMERABIN_FLAG_VIDEO_COLOR_CONVERSION,
                NULL);

  bus = gst_element_get_bus (camerabin);
  gst_bus_add_signal_watch (bus);

  g_signal_connect (G_OBJECT (bus), "message",
                    G_CALLBACK (cheese_camera_bus_message_cb), NULL);
}

int
main (int argc, char **argv)
{
  g_thread_init (NULL);
  gdk_threads_init ();
  gst_init (&argc, &argv);

  gtk_init (&argc, &argv);

  gdk_threads_enter ();
  cheese_camera_init ();
  gdk_threads_leave ();

  cheese_camera_play ();

  g_timeout_add_seconds (5, (GSourceFunc) (cheese_camera_start_video_recording), "testcamera.ogv");
  g_timeout_add_seconds (15, (GSourceFunc) (cheese_camera_stop_video_recording), NULL);

  gtk_main ();

  return 0;
}
