3 * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 * This is a demo application to test the camerabin element.
22 * If you have question don't hesitate in contact me edgard.lima@indt.org.br
32 #include "gst-camera.h"
35 #include <gst/interfaces/xoverlay.h>
36 #include <gst/interfaces/colorbalance.h>
37 #include <gst/interfaces/photography.h>
40 #include <gdk/gdkkeysyms.h>
46 #include <glib/gstdio.h> // g_fopen()
49 * enums, typedefs and defines
53 #define VID_FILE_EXT "mp4"
55 #define VID_FILE_EXT "ogg"
58 #define PREVIEW_TIME_MS (2 * 1000)
59 #define N_BURST_IMAGES 10
60 #define DEFAULT_UI_FILE "gst-camera.ui"
61 #define SHARED_UI_FILE CAMERA_APPS_UIDIR"/"DEFAULT_UI_FILE
63 /* Names of default elements */
64 #define CAMERA_APP_VIDEOSRC "v4l2src"
65 #define CAMERA_APP_IMAGE_POSTPROC "dummy"
67 #ifdef HAVE_GST_PHOTO_IFACE_H
68 #define EV_COMP_MAX 3.0
69 #define EV_COMP_MIN -3.0
70 #define EV_COMP_STEP 0.5
73 #define DEFAULT_VF_CAPS \
74 "video/x-raw-yuv, width = (int) 320, height = (int) 240, framerate = (fraction) 1496/100;" \
75 "video/x-raw-yuv, width = (int) 640, height = (int) 480, framerate = (fraction) 1494/100;" \
76 "video/x-raw-yuv, width = (int) 800, height = (int) 480, framerate = (fraction) 2503/100;" \
77 "video/x-raw-yuv, width = (int) 800, height = (int) 480, framerate = (fraction) 2988/100;" \
78 "video/x-raw-yuv, width = (int) 800, height = (int) 480, framerate = (fraction) 1494/100;" \
79 "video/x-raw-yuv, width = (int) 720, height = (int) 480, framerate = (fraction) 1494/100"
81 #define PREVIEW_CAPS \
82 "video/x-raw-rgb, width = (int) 640, height = (int) 480"
85 (image) <---> (video_stopped) <---> (video_recording)
87 typedef enum _tag_CaptureState
90 CAP_STATE_VIDEO_STOPED,
91 CAP_STATE_VIDEO_PAUSED,
92 CAP_STATE_VIDEO_RECORDING,
99 static GtkBuilder *builder = NULL;
100 static GtkWidget *ui_main_window = NULL;
101 static GtkWidget *ui_drawing = NULL;
102 static GtkWidget *ui_drawing_frame = NULL;
103 static GtkWidget *ui_chk_continous = NULL;
104 static GtkButton *ui_bnt_shot = NULL;
105 static GtkButton *ui_bnt_pause = NULL;
106 static GtkWidget *ui_chk_mute = NULL;
107 static GtkWidget *ui_vbox_color_controls = NULL;
108 static GtkWidget *ui_chk_rawmsg = NULL;
110 static GtkWidget *ui_rdbntImageCapture = NULL;
111 static GtkWidget *ui_rdbntVideoCapture = NULL;
112 static GtkWidget *ui_menuitem_photography = NULL;
113 static GtkWidget *ui_menuitem_capture = NULL;
115 static GtkComboBox *ui_cbbox_resolution = NULL;
116 static guint ui_cbbox_resolution_count = 0;
118 static CaptureState capture_state = CAP_STATE_IMAGE;
120 static GstElement *gst_camera_bin = NULL;
121 static GstElement *gst_videosrc = NULL;
123 static GString *filename = NULL;
124 static guint32 num_pics = 0;
125 static guint32 num_pics_cont = 0;
126 static guint32 num_vids = 0;
128 static gint max_fr_n = 0;
129 static gint max_fr_d = 0;
130 static const gchar *video_post;
131 static const gchar *image_post;
133 static GList *video_caps_list = NULL;
135 static guint bus_handler_id = 0;
137 #ifdef HAVE_GST_PHOTO_IFACE_H
138 static gchar *iso_speed_labels[] = { "auto", "100", "200", "400" };
145 } image_resolution_label_map[] = {
147 "View finder resolution", 0, 0}, {
149 "1,3Mpix (1280x960)", 1280, 960}, {
150 "3Mpix (2048x1536)", 2048, 1536}, {
151 "3,7Mpix 16:9 (2592x1456)", 2592, 1456}, {
152 "5Mpix (2592x1968)", 2592, 1968}
157 * functions prototypes
159 static gboolean me_gst_setup_pipeline (const gchar * imagepost,
160 const gchar * videopost);
161 static void me_gst_cleanup_element (void);
163 static gboolean capture_mode_set_state (CaptureState state);
164 static void capture_mode_config_gui (void);
165 static gboolean capture_mode_stop (void);
167 static void ui_connect_signals (void);
168 static gboolean ui_create (void);
169 static void destroy_color_controls (void);
170 static void create_color_controls (void);
171 static void init_view_finder_resolution_combobox (void);
173 #ifdef HAVE_GST_PHOTO_IFACE_H
174 static void menuitem_toggle_active (GtkWidget * widget, gpointer data);
175 static void sub_menu_initialize (GtkWidget * widget, gpointer data);
176 static void fill_photography_menu (GtkMenuItem * parent_item);
180 * functions implementation
184 set_filename (GString * name)
186 const gchar *datadir;
188 if (capture_state == CAP_STATE_IMAGE) {
189 g_string_printf (name, G_DIR_SEPARATOR_S "test_%04u.jpg", num_pics);
190 datadir = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
192 g_string_printf (name, G_DIR_SEPARATOR_S "test_%04u.%s", num_vids,
194 datadir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS);
197 if (datadir == NULL) {
198 gchar *curdir = g_get_current_dir ();
199 g_string_prepend (name, curdir);
202 g_string_prepend (name, datadir);
204 GST_INFO ("capture to %s", name->str);
207 /* Write raw image buffer to file if found from message */
209 handle_element_message (GstMessage * msg)
211 const GstStructure *st;
213 GstBuffer *buf = NULL;
217 gchar *filename = NULL;
221 st = gst_message_get_structure (msg);
222 if (g_str_equal (gst_structure_get_name (st), "autofocus-done")) {
223 gtk_button_set_label (ui_bnt_pause, "Focus");
224 } else if (gst_structure_has_field_typed (st, "buffer", GST_TYPE_BUFFER)) {
225 image = gst_structure_get_value (st, "buffer");
227 buf = gst_value_get_buffer (image);
228 data = GST_BUFFER_DATA (buf);
229 size = GST_BUFFER_SIZE (buf);
230 if (g_str_equal (gst_structure_get_name (st), "raw-image")) {
231 filename = g_strdup_printf ("test_%04u.raw", num_pics);
232 } else if (g_str_equal (gst_structure_get_name (st), "preview-image")) {
233 filename = g_strdup_printf ("test_%04u_vga.rgb", num_pics);
235 /* for future purposes */
236 g_print ("unknown buffer received\n");
239 caps_string = gst_caps_to_string (GST_BUFFER_CAPS (buf));
240 g_print ("writing buffer to %s, buffer caps: %s\n",
241 filename, caps_string);
242 g_free (caps_string);
243 f = g_fopen (filename, "w");
245 written = fwrite (data, size, 1, f);
247 g_print ("errro writing file\n");
251 g_print ("error opening file for raw image writing\n");
255 } else if (g_str_equal (gst_structure_get_name (st), "photo-capture-start")) {
256 g_print ("=== CLICK ===\n");
260 static GstBusSyncReply
261 my_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
263 if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
266 if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
269 /* FIXME: make sure to get XID in main thread */
270 gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (message->src),
271 GDK_WINDOW_XWINDOW (ui_drawing->window));
273 gst_message_unref (message);
278 print_error_message (GstMessage * msg)
283 gst_message_parse_error (msg, &err, &dbg);
285 g_printerr ("Camerabin won't start up!\nError: %s\nDebug Info: %s\n",
286 err->message, (dbg) ? dbg : "None");
293 my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
295 switch (GST_MESSAGE_TYPE (message)) {
296 case GST_MESSAGE_WARNING:{
300 gst_message_parse_warning (message, &err, &debug);
301 g_print ("Warning: %s\n", err->message);
306 case GST_MESSAGE_ERROR:{
307 print_error_message (message);
308 me_gst_cleanup_element ();
312 case GST_MESSAGE_EOS:
316 case GST_MESSAGE_STATE_CHANGED:{
317 GstState old, new, pending;
319 gst_message_parse_state_changed (message, &old, &new, &pending);
321 GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), "state-change %s -> %s",
322 gst_element_state_get_name (old), gst_element_state_get_name (new));
324 /* Create/destroy color controls according videosrc state */
325 if (GST_MESSAGE_SRC (message) == GST_OBJECT (gst_videosrc)) {
326 GST_INFO_OBJECT (GST_MESSAGE_SRC (message), "state-change %s -> %s",
327 gst_element_state_get_name (old), gst_element_state_get_name (new));
329 if (old == GST_STATE_READY && new == GST_STATE_NULL) {
330 destroy_color_controls ();
331 } else if (old == GST_STATE_NULL && new == GST_STATE_READY) {
332 create_color_controls ();
336 /* we only care about pipeline state change messages */
337 if (GST_IS_PIPELINE (GST_MESSAGE_SRC (message))) {
338 /* dump graph for pipeline state changes */
339 gchar *dump_name = g_strdup_printf ("camerabin.%s_%s",
340 gst_element_state_get_name (old),
341 gst_element_state_get_name (new));
342 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (GST_MESSAGE_SRC (message)),
343 GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE |
344 GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS, dump_name);
349 case GST_MESSAGE_ELEMENT:
351 handle_element_message (message);
355 /* unhandled message */
362 me_set_next_cont_file_name (GString * filename)
364 /* FIXME: better file naming (possible with signal) */
365 if (G_UNLIKELY (num_pics_cont == 1)) {
367 for (i = filename->len - 1; i > 0; --i) {
368 if (filename->str[i] == '.')
371 g_string_insert (filename, i, "_0001");
375 for (i = filename->len - 1; i > 0; --i) {
376 if (filename->str[i] == '_')
379 snprintf (tmp, 6, "_%04d", num_pics_cont);
380 memcpy (filename->str + i, tmp, 5);
385 stop_image_preview (gpointer data)
387 g_return_val_if_fail (data != NULL, FALSE);
389 g_signal_emit_by_name (data, "capture-stop", 0);
395 me_image_capture_done (GstElement * camera, const gchar * fname,
399 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui_chk_continous));
400 GString *filename = g_string_new (fname);
402 if (num_pics_cont < N_BURST_IMAGES && cont) {
404 me_set_next_cont_file_name (filename);
405 g_object_set (G_OBJECT (camera), "filename", filename->str, NULL);
406 g_string_free (filename, TRUE);
408 gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_shot), TRUE);
409 printf ("%u image(s) saved\n", num_pics_cont + 1);
413 g_timeout_add (PREVIEW_TIME_MS, (GSourceFunc) stop_image_preview, camera);
421 me_gst_setup_pipeline_create_post_bin (const gchar * post, gboolean video)
423 GstElement *vpp = NULL;
424 GstElement *bin, *c1, *c2, *filter;
428 /* this function uses a bin just because it needs ffmpegcolorspace. For
429 * performance reason one should provide an element without need for color
432 vpp = gst_element_factory_make (post, NULL);
434 fprintf (stderr, "cannot create \'%s\' element\n", post);
438 c1 = gst_element_factory_make ("ffmpegcolorspace", NULL);
439 c2 = gst_element_factory_make ("ffmpegcolorspace", NULL);
440 if (NULL == c1 || NULL == c2) {
441 fprintf (stderr, "cannot create \'ffmpegcolorspace\' element\n");
445 filter = gst_element_factory_make ("capsfilter", NULL);
446 if (NULL == filter) {
447 fprintf (stderr, "cannot create \'capsfilter\' element\n");
451 bin = gst_bin_new (video ? "vid_postproc_bin" : "img_postproc_bin");
456 caps = gst_caps_new_simple ("video/x-raw-yuv",
457 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), NULL);
458 g_object_set (G_OBJECT (filter), "caps", caps, NULL);
459 gst_caps_unref (caps);
461 gst_bin_add_many (GST_BIN (bin), c1, vpp, c2, filter, NULL);
462 if (!gst_element_link_many (c1, vpp, c2, filter, NULL)) {
463 fprintf (stderr, "cannot link video post proc elements\n");
468 pad = gst_element_get_static_pad (c1, "sink");
469 gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
470 gst_object_unref (GST_OBJECT (pad));
472 pad = gst_element_get_static_pad (filter, "src");
473 gst_element_add_pad (bin, gst_ghost_pad_new ("src", pad));
474 gst_object_unref (GST_OBJECT (pad));
476 g_object_set (gst_camera_bin,
477 (video ? "video-post-processing" : "image-post-processing"), bin, NULL);
484 me_gst_setup_pipeline_create_codecs (void)
487 g_object_set (gst_camera_bin, "video-encoder",
488 gst_element_factory_make ("omx_mpeg4enc", NULL), NULL);
490 g_object_set (gst_camera_bin, "audio-encoder",
491 gst_element_factory_make ("omx_aacenc", NULL), NULL);
493 g_object_set (gst_camera_bin, "video-muxer",
494 gst_element_factory_make ("hantromp4mux", NULL), NULL);
496 /* using defaults theora, vorbis, ogg */
501 me_gst_setup_pipeline_create_img_post_bin (const gchar * imagepost)
503 return me_gst_setup_pipeline_create_post_bin (imagepost, FALSE);
507 me_gst_setup_pipeline_create_vid_post_bin (const gchar * videopost)
509 return me_gst_setup_pipeline_create_post_bin (videopost, TRUE);
513 me_gst_setup_pipeline (const gchar * imagepost, const gchar * videopost)
516 GstCaps *preview_caps;
518 set_filename (filename);
520 me_gst_cleanup_element ();
522 gst_camera_bin = gst_element_factory_make ("camerabin", NULL);
523 if (NULL == gst_camera_bin) {
527 g_signal_connect (gst_camera_bin, "image-done",
528 (GCallback) me_image_capture_done, NULL);
530 preview_caps = gst_caps_from_string (PREVIEW_CAPS);
532 bus = gst_pipeline_get_bus (GST_PIPELINE (gst_camera_bin));
533 bus_handler_id = gst_bus_add_watch (bus, my_bus_callback, NULL);
534 gst_bus_set_sync_handler (bus, my_bus_sync_callback, NULL);
535 gst_object_unref (bus);
538 g_object_set (gst_camera_bin, "filename", filename->str, NULL);
539 g_object_set (gst_camera_bin, "preview-caps", preview_caps, NULL);
540 gst_caps_unref (preview_caps);
542 gst_videosrc = gst_element_factory_make (CAMERA_APP_VIDEOSRC, NULL);
544 g_object_set (G_OBJECT (gst_camera_bin), "video-source", gst_videosrc,
549 if (!me_gst_setup_pipeline_create_img_post_bin (imagepost))
552 /* Use default image postprocessing element */
554 gst_element_factory_make (CAMERA_APP_IMAGE_POSTPROC, NULL);
556 g_object_set (G_OBJECT (gst_camera_bin), "image-post-processing", ipp,
562 if (!me_gst_setup_pipeline_create_vid_post_bin (videopost))
566 me_gst_setup_pipeline_create_codecs ();
568 if (GST_STATE_CHANGE_FAILURE ==
569 gst_element_set_state (gst_camera_bin, GST_STATE_READY)) {
574 g_object_get (G_OBJECT (gst_camera_bin), "video-source", &gst_videosrc,
578 init_view_finder_resolution_combobox ();
580 gst_element_set_state (gst_camera_bin, GST_STATE_PLAYING);
582 #ifdef HAVE_GST_PHOTO_IFACE_H
583 /* Initialize menus to default settings */
584 GtkWidget *sub_menu =
585 gtk_menu_item_get_submenu (GTK_MENU_ITEM (ui_menuitem_capture));
586 gtk_container_foreach (GTK_CONTAINER (sub_menu), sub_menu_initialize, NULL);
588 gtk_menu_item_get_submenu (GTK_MENU_ITEM (ui_menuitem_photography));
589 gtk_container_foreach (GTK_CONTAINER (sub_menu), sub_menu_initialize, NULL);
592 capture_state = CAP_STATE_IMAGE;
595 fprintf (stderr, "error to create pipeline\n");
597 me_gst_cleanup_element ();
602 me_gst_setup_default_pipeline (gpointer data)
604 if (!me_gst_setup_pipeline (NULL, NULL)) {
611 me_gst_cleanup_element (void)
613 if (gst_camera_bin) {
616 gst_element_set_state (gst_camera_bin, GST_STATE_NULL);
617 gst_element_get_state (gst_camera_bin, NULL, NULL, GST_CLOCK_TIME_NONE);
619 bus = gst_pipeline_get_bus (GST_PIPELINE (gst_camera_bin));
620 gst_bus_set_sync_handler (bus, NULL, NULL);
621 g_source_remove (bus_handler_id);
623 gst_object_unref (gst_camera_bin);
624 gst_camera_bin = NULL;
626 g_list_foreach (video_caps_list, (GFunc) gst_caps_unref, NULL);
627 g_list_free (video_caps_list);
628 video_caps_list = NULL;
633 capture_mode_stop (void)
635 if (capture_state == CAP_STATE_VIDEO_PAUSED
636 || capture_state == CAP_STATE_VIDEO_RECORDING) {
637 return capture_mode_set_state (CAP_STATE_VIDEO_STOPED);
644 capture_mode_config_gui (void)
646 switch (capture_state) {
647 case CAP_STATE_IMAGE:
648 gtk_button_set_label (ui_bnt_shot, "Shot");
649 gtk_button_set_label (ui_bnt_pause, "Focus");
650 gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_pause), TRUE);
651 gtk_widget_show (ui_chk_continous);
652 gtk_widget_show (ui_chk_rawmsg);
653 gtk_widget_hide (ui_chk_mute);
654 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui_rdbntImageCapture),
657 case CAP_STATE_VIDEO_STOPED:
658 gtk_button_set_label (ui_bnt_shot, "Rec");
659 gtk_button_set_label (ui_bnt_pause, "Pause");
660 gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_pause), FALSE);
661 gtk_widget_show (GTK_WIDGET (ui_bnt_pause));
662 gtk_widget_show (ui_chk_mute);
663 gtk_widget_hide (ui_chk_continous);
664 gtk_widget_hide (ui_chk_rawmsg);
665 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui_rdbntVideoCapture),
668 case CAP_STATE_VIDEO_PAUSED:
669 gtk_button_set_label (ui_bnt_pause, "Cont");
671 case CAP_STATE_VIDEO_RECORDING:
672 gtk_button_set_label (ui_bnt_shot, "Stop");
673 gtk_button_set_label (ui_bnt_pause, "Pause");
674 gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_pause), TRUE);
682 capture_mode_set_state (CaptureState state)
684 if (capture_state == state)
687 switch (capture_state) {
688 case CAP_STATE_IMAGE:
689 if (state == CAP_STATE_VIDEO_PAUSED) {
692 g_object_set (gst_camera_bin, "mode", 1, NULL);
693 capture_state = CAP_STATE_VIDEO_STOPED;
694 if (state == CAP_STATE_VIDEO_RECORDING)
695 capture_mode_set_state (state);
697 case CAP_STATE_VIDEO_STOPED:
698 if (state == CAP_STATE_VIDEO_PAUSED) {
701 capture_state = state;
702 if (state == CAP_STATE_IMAGE)
703 g_object_set (gst_camera_bin, "mode", 0, NULL);
704 else { /* state == CAP_STATE_VIDEO_RECORDING */
705 g_object_set (gst_camera_bin, "mode", 1, NULL);
706 g_signal_emit_by_name (gst_camera_bin, "capture-start", 0);
709 case CAP_STATE_VIDEO_PAUSED:
710 if (state == CAP_STATE_VIDEO_RECORDING) {
711 g_signal_emit_by_name (gst_camera_bin, "capture-start", 0);
712 capture_state = CAP_STATE_VIDEO_RECORDING;
714 g_signal_emit_by_name (gst_camera_bin, "capture-stop", 0);
715 capture_state = CAP_STATE_VIDEO_STOPED;
716 if (state == CAP_STATE_IMAGE)
717 capture_mode_set_state (state);
720 case CAP_STATE_VIDEO_RECORDING:
721 if (state == CAP_STATE_VIDEO_PAUSED) {
722 g_signal_emit_by_name (gst_camera_bin, "capture-pause", 0);
723 capture_state = CAP_STATE_VIDEO_PAUSED;
725 g_signal_emit_by_name (gst_camera_bin, "capture-stop", 0);
726 capture_state = CAP_STATE_VIDEO_STOPED;
727 if (state == CAP_STATE_IMAGE)
728 capture_mode_set_state (state);
738 on_windowMain_delete_event (GtkWidget * widget, GdkEvent * event, gpointer data)
740 capture_mode_set_state (CAP_STATE_IMAGE);
741 capture_mode_config_gui ();
742 me_gst_cleanup_element ();
749 /* for more information about image metadata tags, see:
750 * http://webcvs.freedesktop.org/gstreamer/gst-plugins-bad/tests/icles/metadata_editor.c
751 * and for the mapping:
752 * http://webcvs.freedesktop.org/gstreamer/gst-plugins-bad/ext/metadata/metadata_mapping.htm?view=co
755 GstTagSetter *setter = GST_TAG_SETTER (gst_camera_bin);
756 GTimeVal time = { 0, 0 };
757 gchar *date_str, *desc_str;
759 g_get_current_time (&time);
760 date_str = g_time_val_to_iso8601 (&time); /* this is UTC */
761 desc_str = g_strdup_printf ("picture taken by %s", g_get_real_name ());
763 gst_tag_setter_add_tags (setter, GST_TAG_MERGE_REPLACE,
764 "date-time-original", date_str,
765 "date-time-modified", date_str,
766 "creator-tool", "camerabin-demo",
767 GST_TAG_DESCRIPTION, desc_str,
768 GST_TAG_TITLE, "My picture", GST_TAG_COPYRIGHT, "LGPL", NULL);
775 on_buttonShot_clicked (GtkButton * button, gpointer user_data)
777 switch (capture_state) {
778 case CAP_STATE_IMAGE:
780 gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_shot), FALSE);
781 set_filename (filename);
783 g_object_set (gst_camera_bin, "filename", filename->str, NULL);
786 g_signal_emit_by_name (gst_camera_bin, "capture-start", 0);
789 case CAP_STATE_VIDEO_STOPED:
790 set_filename (filename);
792 g_object_set (gst_camera_bin, "filename", filename->str, NULL);
793 capture_mode_set_state (CAP_STATE_VIDEO_RECORDING);
794 capture_mode_config_gui ();
796 case CAP_STATE_VIDEO_PAUSED:
798 case CAP_STATE_VIDEO_RECORDING:
799 capture_mode_set_state (CAP_STATE_VIDEO_STOPED);
800 capture_mode_config_gui ();
808 on_buttonPause_clicked (GtkButton * button, gpointer user_data)
810 switch (capture_state) {
811 case CAP_STATE_IMAGE:
812 if (g_str_equal (gtk_button_get_label (ui_bnt_pause), "Focus")) {
813 /* Start autofocus */
814 gst_photography_set_autofocus (GST_PHOTOGRAPHY (gst_camera_bin), TRUE);
815 gtk_button_set_label (ui_bnt_pause, "Cancel Focus");
817 /* Cancel autofocus */
818 gst_photography_set_autofocus (GST_PHOTOGRAPHY (gst_camera_bin), FALSE);
819 gtk_button_set_label (ui_bnt_pause, "Focus");
822 case CAP_STATE_VIDEO_STOPED:
824 case CAP_STATE_VIDEO_PAUSED:
825 capture_mode_set_state (CAP_STATE_VIDEO_RECORDING);
826 capture_mode_config_gui ();
828 case CAP_STATE_VIDEO_RECORDING:
829 capture_mode_set_state (CAP_STATE_VIDEO_PAUSED);
830 capture_mode_config_gui ();
838 on_drawingareaView_realize (GtkWidget * widget, gpointer data)
840 #if GTK_CHECK_VERSION (2, 18, 0)
841 gdk_window_ensure_native (widget->window);
846 on_drawingareaView_configure_event (GtkWidget * widget,
847 GdkEventConfigure * event, gpointer data)
849 gdk_window_move_resize (widget->window,
850 widget->allocation.x, widget->allocation.y,
851 widget->allocation.width, widget->allocation.height);
852 gdk_display_sync (gtk_widget_get_display (widget));
858 on_comboboxResolution_changed (GtkComboBox * widget, gpointer user_data)
862 GstCaps *video_caps =
863 g_list_nth_data (video_caps_list, gtk_combo_box_get_active (widget));
868 gst_element_get_state (gst_camera_bin, &old, NULL, GST_CLOCK_TIME_NONE);
869 GST_DEBUG ("change resolution in %s", gst_element_state_get_name (old));
871 if (old != GST_STATE_NULL) {
872 gst_element_set_state (gst_camera_bin, GST_STATE_READY);
873 /* source need to be NULL, otherwise changing the mode fails with device
875 * - if src goes from NULL->PLAYING it sets new mode anyway
876 * - if src goes form READY->PLAYIN new mode is activated via reverse caps
877 * negotiation, but then the device is already streaming
879 gst_element_set_state (gst_videosrc, GST_STATE_NULL);
882 st = gst_caps_get_structure (video_caps, 0);
884 gst_structure_get_int (st, "width", &w);
885 gst_structure_get_int (st, "height", &h);
888 g_object_set (ui_drawing_frame, "ratio", (gfloat) w / (gfloat) h, NULL);
891 g_object_set (G_OBJECT (gst_camera_bin), "filter-caps", video_caps, NULL);
893 if (old != GST_STATE_NULL) {
894 gst_element_set_state (gst_camera_bin, old);
900 on_radiobuttonImageCapture_toggled (GtkToggleButton * togglebutton,
903 if (gtk_toggle_button_get_active (togglebutton)) {
904 if (capture_state != CAP_STATE_IMAGE) {
905 capture_mode_set_state (CAP_STATE_IMAGE);
906 capture_mode_config_gui ();
912 on_radiobuttonVideoCapture_toggled (GtkToggleButton * togglebutton,
915 if (gtk_toggle_button_get_active (togglebutton)) {
916 if (capture_state == CAP_STATE_IMAGE) {
917 capture_mode_set_state (CAP_STATE_VIDEO_STOPED);
918 capture_mode_config_gui ();
924 on_rbBntVidEff_toggled (GtkToggleButton * togglebutton, const gchar * effect)
926 if (gtk_toggle_button_get_active (togglebutton)) {
927 /* lets also use those effects to image */
930 capture_mode_stop ();
932 me_gst_cleanup_element ();
933 if (!me_gst_setup_pipeline (image_post, video_post))
935 capture_mode_config_gui ();
940 on_rbBntVidEffNone_toggled (GtkToggleButton * togglebutton, gpointer data)
942 on_rbBntVidEff_toggled (togglebutton, NULL);
946 on_rbBntVidEffEdge_toggled (GtkToggleButton * togglebutton, gpointer data)
948 on_rbBntVidEff_toggled (togglebutton, "edgetv");
952 on_rbBntVidEffAging_toggled (GtkToggleButton * togglebutton, gpointer user_data)
954 on_rbBntVidEff_toggled (togglebutton, "agingtv");
958 on_rbBntVidEffDice_toggled (GtkToggleButton * togglebutton, gpointer user_data)
960 on_rbBntVidEff_toggled (togglebutton, "dicetv");
964 on_rbBntVidEffWarp_toggled (GtkToggleButton * togglebutton, gpointer data)
966 on_rbBntVidEff_toggled (togglebutton, "warptv");
970 on_rbBntVidEffShagadelic_toggled (GtkToggleButton * togglebutton, gpointer data)
972 on_rbBntVidEff_toggled (togglebutton, "shagadelictv");
976 on_rbBntVidEffVertigo_toggled (GtkToggleButton * togglebutton, gpointer data)
978 on_rbBntVidEff_toggled (togglebutton, "vertigotv");
982 on_rbBntVidEffRev_toggled (GtkToggleButton * togglebutton, gpointer data)
984 on_rbBntVidEff_toggled (togglebutton, "revtv");
988 on_rbBntVidEffQuark_toggled (GtkToggleButton * togglebutton, gpointer data)
990 on_rbBntVidEff_toggled (togglebutton, "quarktv");
994 on_chkbntMute_toggled (GtkToggleButton * togglebutton, gpointer data)
996 g_object_set (gst_camera_bin, "mute",
997 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton)), NULL);
1001 on_chkbtnRawMsg_toggled (GtkToggleButton * togglebutton, gpointer data)
1003 const gchar *env_var = "CAMSRC_PUBLISH_RAW";
1004 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton))) {
1005 g_setenv (env_var, "1", TRUE);
1007 g_unsetenv (env_var);
1012 on_hscaleZoom_value_changed (GtkRange * range, gpointer user_data)
1014 gint zoom = gtk_range_get_value (range);
1015 g_object_set (gst_camera_bin, "zoom", zoom, NULL);
1019 on_color_control_value_changed (GtkRange * range, gpointer user_data)
1021 GstColorBalance *balance = GST_COLOR_BALANCE (gst_camera_bin);
1022 gint val = gtk_range_get_value (range);
1023 GstColorBalanceChannel *channel = (GstColorBalanceChannel *) user_data;
1024 gst_color_balance_set_value (balance, channel, val);
1029 on_key_released (GtkWidget * widget, GdkEventKey * event, gpointer user_data)
1031 g_return_val_if_fail (event != NULL, FALSE);
1033 switch (event->keyval) {
1035 #ifdef HAVE_GST_PHOTO_IFACE_H
1036 gst_photography_set_autofocus (GST_PHOTOGRAPHY (gst_camera_bin), FALSE);
1047 on_key_pressed (GtkWidget * widget, GdkEventKey * event, gpointer user_data)
1049 g_return_val_if_fail (event != NULL, FALSE);
1051 switch (event->keyval) {
1053 #ifdef HAVE_GST_PHOTO_IFACE_H
1054 gst_photography_set_autofocus (GST_PHOTOGRAPHY (gst_camera_bin), TRUE);
1058 on_buttonShot_clicked (NULL, NULL);
1068 ui_connect_signals (void)
1070 gtk_builder_connect_signals (builder, NULL);
1072 g_signal_connect (ui_main_window, "key-press-event",
1073 (GCallback) on_key_pressed, NULL);
1075 g_signal_connect (ui_main_window, "key-release-event",
1076 (GCallback) on_key_released, NULL);
1080 format_value_callback (GtkScale * scale, gdouble value, gpointer user_data)
1082 GstColorBalanceChannel *channel = (GstColorBalanceChannel *) user_data;
1084 return g_strdup_printf ("%s: %d", channel->label, (gint) value);
1088 create_menu_items_from_structure (GstStructure * structure)
1090 const GValue *framerate_list = NULL;
1091 const gchar *structure_name;
1092 GString *item_str = NULL;
1093 guint j, num_items_created = 0, num_framerates = 1;
1094 gint w = 0, h = 0, n = 0, d = 1;
1097 g_return_val_if_fail (structure != NULL, 0);
1099 structure_name = gst_structure_get_name (structure);
1101 /* lets filter yuv only */
1102 if (0 == strcmp (structure_name, "video/x-raw-yuv")) {
1103 item_str = g_string_new_len ("", 128);
1105 if (gst_structure_has_field_typed (structure, "format", GST_TYPE_FOURCC)) {
1106 gst_structure_get_fourcc (structure, "format", &fourcc);
1109 if (gst_structure_has_field_typed (structure, "width", GST_TYPE_INT_RANGE)) {
1110 const GValue *wrange = gst_structure_get_value (structure, "width");
1111 /* If range found, use the maximum */
1112 w = gst_value_get_int_range_max (wrange);
1113 } else if (gst_structure_has_field_typed (structure, "width", G_TYPE_INT)) {
1114 gst_structure_get_int (structure, "width", &w);
1117 if (gst_structure_has_field_typed (structure, "height", GST_TYPE_INT_RANGE)) {
1118 const GValue *hrange = gst_structure_get_value (structure, "height");
1119 /* If range found, use the maximum */
1120 h = gst_value_get_int_range_max (hrange);
1121 } else if (gst_structure_has_field_typed (structure, "height", G_TYPE_INT)) {
1122 gst_structure_get_int (structure, "height", &h);
1125 if (gst_structure_has_field_typed (structure, "framerate",
1126 GST_TYPE_FRACTION)) {
1127 gst_structure_get_fraction (structure, "framerate", &n, &d);
1128 } else if (gst_structure_has_field_typed (structure, "framerate",
1130 framerate_list = gst_structure_get_value (structure, "framerate");
1131 num_framerates = gst_value_list_get_size (framerate_list);
1132 } else if (gst_structure_has_field_typed (structure, "framerate",
1133 GST_TYPE_FRACTION_RANGE)) {
1134 const GValue *fr = gst_structure_get_value (structure, "framerate");
1135 const GValue *frmax = gst_value_get_fraction_range_max (fr);
1136 max_fr_n = gst_value_get_fraction_numerator (frmax);
1137 max_fr_d = gst_value_get_fraction_denominator (frmax);
1140 if (max_fr_n || max_fr_d) {
1144 for (j = 0; j < num_framerates; j++) {
1145 GstCaps *video_caps;
1147 if (framerate_list) {
1148 const GValue *item = gst_value_list_get_value (framerate_list, j);
1149 n = gst_value_get_fraction_numerator (item);
1150 d = gst_value_get_fraction_denominator (item);
1152 g_string_assign (item_str, structure_name);
1153 g_string_append_printf (item_str, " (%" GST_FOURCC_FORMAT ")",
1154 GST_FOURCC_ARGS (fourcc));
1155 g_string_append_printf (item_str, ", %dx%d at %d/%d", w, h, n, d);
1156 gtk_combo_box_append_text (ui_cbbox_resolution, item_str->str);
1159 gst_caps_new_simple (structure_name, "format", GST_TYPE_FOURCC,
1161 "width", G_TYPE_INT, w, "height", G_TYPE_INT, h,
1162 "framerate", GST_TYPE_FRACTION, n, d, NULL);
1163 video_caps_list = g_list_append (video_caps_list, video_caps);
1164 num_items_created++;
1171 g_string_free (item_str, TRUE);
1174 return num_items_created;
1178 fill_resolution_combo (GstCaps * caps)
1180 guint size, num_items, i;
1183 max_fr_n = max_fr_d = 0;
1185 /* Create new items */
1186 size = gst_caps_get_size (caps);
1188 for (i = 0; i < size; i++) {
1189 st = gst_caps_get_structure (caps, i);
1190 num_items = create_menu_items_from_structure (st);
1191 ui_cbbox_resolution_count += num_items;
1196 create_default_caps (void)
1198 GstCaps *default_caps;
1200 default_caps = gst_caps_from_string (DEFAULT_VF_CAPS);
1202 return default_caps;
1206 init_view_finder_resolution_combobox (void)
1208 GstCaps *input_caps = NULL, *default_caps = NULL, *intersect = NULL;
1210 g_object_get (gst_camera_bin, "video-source-caps", &input_caps, NULL);
1212 fill_resolution_combo (input_caps);
1215 /* Fill in default items if supported */
1216 default_caps = create_default_caps ();
1217 intersect = gst_caps_intersect (default_caps, input_caps);
1219 fill_resolution_combo (intersect);
1220 gst_caps_unref (intersect);
1222 gst_caps_unref (default_caps);
1225 gst_caps_unref (input_caps);
1228 /* Set some item active */
1229 gtk_combo_box_set_active (ui_cbbox_resolution, ui_cbbox_resolution_count - 1);
1233 destroy_color_controls (void)
1235 GList *widgets, *item;
1236 GtkWidget *widget = NULL;
1237 gpointer user_data = NULL;
1239 widgets = gtk_container_get_children (GTK_CONTAINER (ui_vbox_color_controls));
1240 for (item = widgets; item; item = g_list_next (item)) {
1241 widget = GTK_WIDGET (item->data);
1242 user_data = g_object_get_data (G_OBJECT (widget), "channel");
1243 g_signal_handlers_disconnect_by_func (widget, (GFunc) format_value_callback,
1245 g_signal_handlers_disconnect_by_func (widget,
1246 (GFunc) on_color_control_value_changed, user_data);
1247 gtk_container_remove (GTK_CONTAINER (ui_vbox_color_controls), widget);
1249 g_list_free (widgets);
1253 create_color_controls (void)
1255 GstColorBalance *balance = NULL;
1256 const GList *controls, *item;
1257 GstColorBalanceChannel *channel;
1260 if (GST_IS_COLOR_BALANCE (gst_camera_bin)) {
1261 balance = GST_COLOR_BALANCE (gst_camera_bin);
1264 if (NULL == balance) {
1268 controls = gst_color_balance_list_channels (balance);
1269 for (item = controls; item; item = g_list_next (item)) {
1270 channel = item->data;
1272 hscale = gtk_hscale_new ((GtkAdjustment *)
1273 gtk_adjustment_new (gst_color_balance_get_value (balance, channel),
1274 channel->min_value, channel->max_value, 1, 10, 10));
1276 g_signal_connect (GTK_RANGE (hscale), "value-changed",
1277 (GCallback) on_color_control_value_changed, (gpointer) channel);
1278 g_signal_connect (GTK_SCALE (hscale), "format-value",
1279 (GCallback) format_value_callback, (gpointer) channel);
1280 g_object_set_data (G_OBJECT (hscale), "channel", (gpointer) channel);
1282 gtk_box_pack_start (GTK_BOX (ui_vbox_color_controls), GTK_WIDGET (hscale),
1286 gtk_widget_show_all (ui_vbox_color_controls);
1291 #ifdef HAVE_GST_PHOTO_IFACE_H
1293 menuitem_toggle_active (GtkWidget * widget, gpointer data)
1296 g_object_get (G_OBJECT (widget), "active", &active, NULL);
1298 gtk_check_menu_item_toggled (GTK_CHECK_MENU_ITEM (widget));
1303 sub_menu_initialize (GtkWidget * widget, gpointer data)
1306 submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
1307 gtk_container_foreach (GTK_CONTAINER (submenu), menuitem_toggle_active, NULL);
1311 photo_menuitem_toggled_cb (GtkRadioMenuItem * menuitem, gpointer user_data)
1313 gboolean active = FALSE, ret = FALSE;
1314 GEnumClass *eclass = (GEnumClass *) user_data;
1315 GType etype = G_ENUM_CLASS_TYPE (eclass);
1317 gint set_value = -1;
1319 /* Get value using menu item name */
1321 g_enum_get_value_by_nick (eclass,
1322 gtk_widget_get_name (GTK_WIDGET (menuitem)));
1324 g_object_get (G_OBJECT (menuitem), "active", &active, NULL);
1326 if (etype == GST_TYPE_WHITE_BALANCE_MODE) {
1327 GstWhiteBalanceMode mode;
1329 gst_photography_set_white_balance_mode (GST_PHOTOGRAPHY
1330 (gst_camera_bin), val->value);
1331 gst_photography_get_white_balance_mode (GST_PHOTOGRAPHY (gst_camera_bin),
1333 set_value = (gint) mode;
1334 } else if (etype == GST_TYPE_SCENE_MODE) {
1337 gst_photography_set_scene_mode (GST_PHOTOGRAPHY (gst_camera_bin),
1339 gst_photography_get_scene_mode (GST_PHOTOGRAPHY (gst_camera_bin), &mode);
1340 set_value = (gint) mode;
1341 } else if (etype == GST_TYPE_COLOUR_TONE_MODE) {
1342 GstColourToneMode mode;
1344 gst_photography_set_colour_tone_mode (GST_PHOTOGRAPHY
1345 (gst_camera_bin), val->value);
1346 gst_photography_get_colour_tone_mode (GST_PHOTOGRAPHY (gst_camera_bin),
1348 set_value = (gint) mode;
1349 } else if (etype == GST_TYPE_FLASH_MODE) {
1352 gst_photography_set_flash_mode (GST_PHOTOGRAPHY (gst_camera_bin),
1354 gst_photography_get_flash_mode (GST_PHOTOGRAPHY (gst_camera_bin), &mode);
1355 set_value = (gint) mode;
1359 g_print ("%s setting failed\n", val->value_name);
1360 } else if (val->value != set_value) {
1361 g_print ("%s setting failed, got %d\n", val->value_nick, set_value);
1367 photo_iso_speed_toggled_cb (GtkRadioMenuItem * menuitem, gpointer user_data)
1371 guint val = 0, set_val = G_MAXUINT;
1373 g_object_get (G_OBJECT (menuitem), "active", &active, NULL);
1375 name = gtk_widget_get_name (GTK_WIDGET (menuitem));
1376 /* iso auto setting = 0 */
1377 /* FIXME: check what values other than 0 can be set */
1378 if (!g_str_equal (name, "auto")) {
1379 sscanf (name, "%d", &val);
1381 if (!gst_photography_set_iso_speed (GST_PHOTOGRAPHY (gst_camera_bin), val)) {
1382 g_print ("ISO speed (%d) setting failed\n", val);
1384 gst_photography_get_iso_speed (GST_PHOTOGRAPHY (gst_camera_bin),
1386 if (val != set_val) {
1387 g_print ("ISO speed (%d) setting failed, got %d\n", val, set_val);
1394 photo_ev_comp_toggled_cb (GtkRadioMenuItem * menuitem, gpointer user_data)
1398 gfloat val = 0.0, set_val = G_MAXFLOAT;
1400 g_object_get (G_OBJECT (menuitem), "active", &active, NULL);
1402 name = gtk_widget_get_name (GTK_WIDGET (menuitem));
1403 sscanf (name, "%f", &val);
1404 if (!gst_photography_set_ev_compensation (GST_PHOTOGRAPHY (gst_camera_bin),
1406 g_print ("EV compensation (%.1f) setting failed\n", val);
1408 gst_photography_get_ev_compensation (GST_PHOTOGRAPHY (gst_camera_bin),
1410 if (val != set_val) {
1411 g_print ("EV compensation (%.1f) setting failed, got %.1f\n", val,
1419 photo_add_submenu_from_enum (GtkMenuItem * parent_item, GType enum_type)
1423 GtkWidget *new_item = NULL, *new_submenu = NULL;
1426 GSList *group = NULL;
1428 g_return_if_fail (parent_item && enum_type && G_TYPE_IS_CLASSED (enum_type));
1430 tclass = g_type_class_ref (enum_type);
1431 eclass = G_ENUM_CLASS (tclass);
1432 new_submenu = gtk_menu_new ();
1434 for (i = 0; i < eclass->n_values; i++) {
1435 val = g_enum_get_value (eclass, i);
1436 new_item = gtk_radio_menu_item_new_with_label (group, val->value_nick);
1437 /* Store enum nick as the menu item name */
1438 gtk_widget_set_name (new_item, val->value_nick);
1439 group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (new_item));
1440 g_signal_connect (new_item, "toggled",
1441 (GCallback) photo_menuitem_toggled_cb, eclass);
1442 gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), new_item);
1443 gtk_widget_show (new_item);
1446 gtk_menu_item_set_submenu (parent_item, new_submenu);
1447 g_type_class_unref (tclass);
1451 add_submenu_from_list (GtkMenuItem * parent_item, GList * labels,
1452 GCallback toggled_cb)
1454 GtkWidget *new_item = NULL, *new_submenu = NULL;
1455 GSList *group = NULL;
1458 new_submenu = gtk_menu_new ();
1460 for (l = labels; l != NULL; l = g_list_next (l)) {
1461 const gchar *label = l->data;
1462 new_item = gtk_radio_menu_item_new_with_label (group, label);
1463 if (g_str_equal (label, "0")) {
1464 /* Let's set zero as default */
1465 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_item), TRUE);
1467 gtk_widget_set_name (new_item, label);
1468 group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (new_item));
1469 g_signal_connect (new_item, "toggled", toggled_cb, NULL);
1470 gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), new_item);
1471 gtk_widget_show (new_item);
1474 gtk_menu_item_set_submenu (parent_item, new_submenu);
1477 static GtkMenuItem *
1478 add_menuitem (GtkMenu * parent_menu, const gchar * item_name)
1480 GtkWidget *new_item;
1482 new_item = gtk_menu_item_new_with_label (item_name);
1483 gtk_menu_shell_append (GTK_MENU_SHELL (parent_menu), new_item);
1484 gtk_widget_show (new_item);
1486 return GTK_MENU_ITEM (new_item);
1490 create_iso_speed_labels (void)
1492 GList *labels = NULL;
1494 for (i = 0; i < G_N_ELEMENTS (iso_speed_labels); i++) {
1495 labels = g_list_append (labels, iso_speed_labels[i]);
1501 create_ev_comp_labels (void)
1503 GList *labels = NULL;
1505 char buf[G_ASCII_DTOSTR_BUF_SIZE];
1507 for (comp = EV_COMP_MIN; comp <= EV_COMP_MAX; comp += EV_COMP_STEP) {
1508 g_ascii_dtostr (buf, sizeof (buf), comp);
1509 labels = g_list_append (labels, g_strdup (buf));
1515 fill_photography_menu (GtkMenuItem * parent_item)
1517 GtkWidget *photo_menu = gtk_menu_new ();
1518 GtkMenuItem *item = NULL;
1519 GList *labels = NULL;
1521 /* Add menu items and create and associate submenus to each item */
1522 item = add_menuitem (GTK_MENU (photo_menu), "AWB");
1523 photo_add_submenu_from_enum (item, GST_TYPE_WHITE_BALANCE_MODE);
1525 item = add_menuitem (GTK_MENU (photo_menu), "Colour Tone");
1526 photo_add_submenu_from_enum (item, GST_TYPE_COLOUR_TONE_MODE);
1528 item = add_menuitem (GTK_MENU (photo_menu), "Scene");
1529 photo_add_submenu_from_enum (item, GST_TYPE_SCENE_MODE);
1531 item = add_menuitem (GTK_MENU (photo_menu), "Flash");
1532 photo_add_submenu_from_enum (item, GST_TYPE_FLASH_MODE);
1534 item = add_menuitem (GTK_MENU (photo_menu), "ISO");
1535 labels = create_iso_speed_labels ();
1536 add_submenu_from_list (item, labels, (GCallback) photo_iso_speed_toggled_cb);
1537 g_list_free (labels);
1539 item = add_menuitem (GTK_MENU (photo_menu), "EV comp");
1540 labels = create_ev_comp_labels ();
1541 add_submenu_from_list (item, labels, (GCallback) photo_ev_comp_toggled_cb);
1542 g_list_free (labels);
1544 gtk_menu_item_set_submenu (parent_item, photo_menu);
1548 capture_image_res_toggled_cb (GtkRadioMenuItem * menuitem, gpointer user_data)
1554 g_object_get (G_OBJECT (menuitem), "active", &active, NULL);
1556 label = gtk_widget_get_name (GTK_WIDGET (menuitem));
1557 /* Look for width and height corresponding to the label */
1558 for (i = 0; i < G_N_ELEMENTS (image_resolution_label_map); i++) {
1559 if (g_str_equal (label, image_resolution_label_map[i].label)) {
1560 /* set found values */
1561 g_signal_emit_by_name (gst_camera_bin, "set-image-resolution",
1562 image_resolution_label_map[i].width,
1563 image_resolution_label_map[i].height, 0);
1571 create_image_resolution_labels (void)
1573 GList *labels = NULL;
1575 for (i = 0; i < G_N_ELEMENTS (image_resolution_label_map); i++) {
1576 labels = g_list_append (labels, image_resolution_label_map[i].label);
1582 fill_capture_menu (GtkMenuItem * parent_item)
1584 GtkWidget *capture_menu = gtk_menu_new ();
1585 GtkMenuItem *item = NULL;
1586 GList *labels = NULL;
1588 /* Add menu items and create and associate submenus to each item */
1589 item = add_menuitem (GTK_MENU (capture_menu), "Image resolution");
1591 labels = create_image_resolution_labels ();
1592 add_submenu_from_list (item, labels,
1593 (GCallback) capture_image_res_toggled_cb);
1594 g_list_free (labels);
1596 gtk_menu_item_set_submenu (parent_item, capture_menu);
1598 #endif /* HAVE_GST_PHOTO_IFACE_H */
1603 GError *error = NULL;
1604 const gchar *uifile = DEFAULT_UI_FILE;
1606 if (!g_file_test (uifile, G_FILE_TEST_EXISTS)) {
1607 uifile = SHARED_UI_FILE;
1610 builder = gtk_builder_new ();
1611 if (!gtk_builder_add_from_file (builder, uifile, &error)) {
1612 g_warning ("Couldn't load builder file: %s", error->message);
1613 g_error_free (error);
1617 ui_main_window = GTK_WIDGET (gtk_builder_get_object (builder, "windowMain"));
1618 ui_drawing = GTK_WIDGET (gtk_builder_get_object (builder, "drawingareaView"));
1620 GTK_WIDGET (gtk_builder_get_object (builder, "drawingareaFrame"));
1622 GTK_WIDGET (gtk_builder_get_object (builder, "chkbntContinous"));
1623 ui_chk_rawmsg = GTK_WIDGET (gtk_builder_get_object (builder, "chkbtnRawMsg"));
1624 ui_bnt_shot = GTK_BUTTON (gtk_builder_get_object (builder, "buttonShot"));
1625 ui_bnt_pause = GTK_BUTTON (gtk_builder_get_object (builder, "buttonPause"));
1626 ui_cbbox_resolution =
1627 GTK_COMBO_BOX (gtk_builder_get_object (builder, "comboboxResolution"));
1628 ui_chk_mute = GTK_WIDGET (gtk_builder_get_object (builder, "chkbntMute"));
1629 ui_vbox_color_controls =
1630 GTK_WIDGET (gtk_builder_get_object (builder, "vboxColorControls"));
1631 ui_rdbntImageCapture =
1632 GTK_WIDGET (gtk_builder_get_object (builder, "radiobuttonImageCapture"));
1633 ui_rdbntVideoCapture =
1634 GTK_WIDGET (gtk_builder_get_object (builder, "radiobuttonVideoCapture"));
1635 ui_menuitem_photography =
1636 GTK_WIDGET (gtk_builder_get_object (builder, "menuitemPhotography"));
1637 ui_menuitem_capture =
1638 GTK_WIDGET (gtk_builder_get_object (builder, "menuitemCapture"));
1640 #ifdef HAVE_GST_PHOTO_IFACE_H
1641 if (ui_menuitem_photography) {
1642 fill_photography_menu (GTK_MENU_ITEM (ui_menuitem_photography));
1645 if (ui_menuitem_capture) {
1646 fill_capture_menu (GTK_MENU_ITEM (ui_menuitem_capture));
1649 if (!(ui_main_window && ui_drawing && ui_chk_continous && ui_bnt_shot &&
1650 ui_bnt_pause && ui_cbbox_resolution && ui_chk_mute &&
1651 ui_vbox_color_controls && ui_rdbntImageCapture &&
1652 ui_rdbntVideoCapture && ui_chk_rawmsg && ui_menuitem_photography &&
1653 ui_menuitem_capture)) {
1654 fprintf (stderr, "Some widgets couldn't be created\n");
1659 gtk_widget_set_double_buffered (ui_drawing, FALSE);
1660 ui_connect_signals ();
1661 gtk_widget_show_all (ui_main_window);
1662 capture_mode_config_gui ();
1673 main (int argc, char *argv[])
1677 gst_init (&argc, &argv);
1678 gtk_init (&argc, &argv);
1680 filename = g_string_new_len ("", 16);
1683 if (!ui_create ()) {
1687 /* create pipeline and run */
1688 g_idle_add (me_gst_setup_default_pipeline, NULL);
1692 me_gst_cleanup_element ();
1693 g_string_free (filename, TRUE);