Pārlūkot izejas kodu

Implement manual controls

Martijn Braam 4 gadi atpakaļ
vecāks
revīzija
5d872860f9
2 mainītis faili ar 179 papildinājumiem un 5 dzēšanām
  1. 75 0
      camera.glade
  2. 104 5
      main.c

+ 75 - 0
camera.glade

@@ -2,6 +2,11 @@
 <!-- Generated with glade 3.37.0 -->
 <interface>
   <requires lib="gtk+" version="3.20"/>
+  <object class="GtkAdjustment" id="control_adj">
+    <property name="upper">100</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">10</property>
+  </object>
   <object class="GtkWindow" id="window">
     <property name="can-focus">False</property>
     <property name="title" translatable="yes">Camera</property>
@@ -42,6 +47,76 @@
                 <property name="position">0</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkBox" id="control_box">
+                <property name="can-focus">False</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="margin-start">10</property>
+                    <property name="margin-end">10</property>
+                    <property name="margin-top">10</property>
+                    <property name="margin-bottom">10</property>
+                    <child>
+                      <object class="GtkLabel" id="control_name">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="margin-end">10</property>
+                        <property name="label" translatable="yes">ISO</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkScale" id="control_slider">
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="adjustment">control_adj</property>
+                        <property name="round-digits">1</property>
+                        <property name="draw-value">False</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkToggleButton" id="control_auto">
+                        <property name="label" translatable="yes">Auto</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">True</property>
+                        <property name="margin-start">10</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="pack-type">end</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <style>
+                  <class name="controlbox"/>
+                </style>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
             <child>
               <object class="GtkBox" id="controls_box">
                 <property name="visible">True</property>

+ 104 - 5
main.c

@@ -19,10 +19,9 @@
 #include "ini.h"
 #include "quickdebayer.h"
 
-enum io_method {
-	IO_METHOD_READ,
-	IO_METHOD_MMAP,
-	IO_METHOD_USERPTR,
+enum user_control {
+	USER_CONTROL_ISO,
+	USER_CONTROL_SHUTTER
 };
 
 #define TIFFTAG_FORWARDMATRIX1 50964
@@ -95,13 +94,17 @@ static int gain = 1;
 static int burst_length = 5;
 static char burst_dir[23];
 static char processing_script[512];
-
+static enum user_control current_control;
 // Widgets
 GtkWidget *preview;
 GtkWidget *error_box;
 GtkWidget *error_message;
 GtkWidget *main_stack;
 GtkWidget *thumb_last;
+GtkWidget *control_box;
+GtkWidget *control_name;
+GtkWidget *control_slider;
+GtkWidget *control_auto;
 
 static int
 xioctl(int fd, int request, void *arg)
@@ -1113,6 +1116,50 @@ on_shutter_clicked(GtkWidget *widget, gpointer user_data)
 	capture = burst_length;
 }
 
+void
+on_preview_tap(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+	if (event->type != GDK_BUTTON_PRESS)
+		return;
+
+	// Handle taps on the controls
+	if (event->y < 32) {
+		if (gtk_widget_is_visible(control_box)) {
+			gtk_widget_hide(control_box);
+			return;
+		} else {
+			gtk_widget_show(control_box);
+		}
+
+		if (event->x < 60 ) {
+			// ISO
+			current_control = USER_CONTROL_ISO;
+			gtk_label_set_text(GTK_LABEL(control_name), "ISO");
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto), auto_gain);
+			gtk_adjustment_set_lower(GTK_ADJUSTMENT(control_slider), 1.0);
+			gtk_adjustment_set_upper(GTK_ADJUSTMENT(control_slider), 1024.0);
+			gtk_adjustment_set_value(GTK_ADJUSTMENT(control_slider), (double)gain);
+
+		} else if (event->x > 60 && event->x < 120) {
+			// Shutter angle
+			current_control = USER_CONTROL_SHUTTER;
+			gtk_label_set_text(GTK_LABEL(control_name), "Shutter");
+			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto), auto_exposure);
+			gtk_adjustment_set_lower(GTK_ADJUSTMENT(control_slider), 1.0);
+			gtk_adjustment_set_upper(GTK_ADJUSTMENT(control_slider), 360.0);
+			gtk_adjustment_set_value(GTK_ADJUSTMENT(control_slider), (double)exposure);
+		}
+
+		return;
+	}
+
+	// Tapped preview image itself, try focussing
+	if (current.has_af_s) {
+		v4l2_ctrl_set(current.fd, V4L2_CID_AUTO_FOCUS_STOP, 1);
+		v4l2_ctrl_set(current.fd, V4L2_CID_AUTO_FOCUS_START, 1);
+	}
+}
+
 void
 on_error_close_clicked(GtkWidget *widget, gpointer user_data)
 {
@@ -1153,6 +1200,49 @@ on_back_clicked(GtkWidget *widget, gpointer user_data)
 	gtk_stack_set_visible_child_name(GTK_STACK(main_stack), "main");
 }
 
+void
+on_control_auto_toggled(GtkToggleButton *widget, gpointer user_data)
+{
+	int fd = current.fd;
+	switch (current_control) {
+		case USER_CONTROL_ISO:
+			auto_gain = gtk_toggle_button_get_active(widget);
+			if (auto_gain) {
+				v4l2_ctrl_set(fd, V4L2_CID_AUTOGAIN, 1);
+			} else {
+				v4l2_ctrl_set(fd, V4L2_CID_AUTOGAIN, 0);
+			}
+			break;
+		case USER_CONTROL_SHUTTER:
+			auto_exposure = gtk_toggle_button_get_active(widget);
+			if (auto_exposure) {
+				v4l2_ctrl_set(fd, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_AUTO);
+			} else {
+				v4l2_ctrl_set(fd, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL);
+			}
+			break;
+	}
+	draw_controls();
+}
+
+void
+on_control_slider_changed(GtkAdjustment *widget, gpointer user_data)
+{
+	double value = gtk_adjustment_get_value(widget);
+
+	switch (current_control) {
+		case USER_CONTROL_ISO:
+			gain = (int)value;
+			v4l2_ctrl_set(current.fd, V4L2_CID_GAIN, gain);
+			break;
+		case USER_CONTROL_SHUTTER:
+			exposure = (int)(value / 360.0 * current.height);
+			v4l2_ctrl_set(current.fd, V4L2_CID_EXPOSURE, exposure);
+			break;
+	}
+	draw_controls();
+}
+
 int
 find_config(char *conffile)
 {
@@ -1300,6 +1390,10 @@ main(int argc, char *argv[])
 	error_message = GTK_WIDGET(gtk_builder_get_object(builder, "error_message"));
 	main_stack = GTK_WIDGET(gtk_builder_get_object(builder, "main_stack"));
 	thumb_last = GTK_WIDGET(gtk_builder_get_object(builder, "thumb_last"));
+	control_box = GTK_WIDGET(gtk_builder_get_object(builder, "control_box"));
+	control_name = GTK_WIDGET(gtk_builder_get_object(builder, "control_name"));
+	control_slider = GTK_WIDGET(gtk_builder_get_object(builder, "control_adj"));
+	control_auto = GTK_WIDGET(gtk_builder_get_object(builder, "control_auto"));
 	g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
 	g_signal_connect(shutter, "clicked", G_CALLBACK(on_shutter_clicked), NULL);
 	g_signal_connect(error_close, "clicked", G_CALLBACK(on_error_close_clicked), NULL);
@@ -1310,6 +1404,11 @@ main(int argc, char *argv[])
 	g_signal_connect(open_directory, "clicked", G_CALLBACK(on_open_directory_clicked), NULL);
 	g_signal_connect(preview, "draw", G_CALLBACK(preview_draw), NULL);
 	g_signal_connect(preview, "configure-event", G_CALLBACK(preview_configure), NULL);
+	gtk_widget_set_events(preview, gtk_widget_get_events(preview) |
+			GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
+	g_signal_connect(preview, "button-press-event", G_CALLBACK(on_preview_tap), NULL);
+	g_signal_connect(control_auto, "toggled", G_CALLBACK(on_control_auto_toggled), NULL);
+	g_signal_connect(control_slider, "value-changed", G_CALLBACK(on_control_slider_changed), NULL);
 
 	GtkCssProvider *provider = gtk_css_provider_new();
 	if (access("camera.css", F_OK) != -1) {