|
@@ -4,6 +4,7 @@
|
|
|
#include "gl_util.h"
|
|
|
#include "io_pipeline.h"
|
|
|
#include "process_pipeline.h"
|
|
|
+#include "state.h"
|
|
|
#include <asm/errno.h>
|
|
|
#include <assert.h>
|
|
|
#include <errno.h>
|
|
@@ -47,30 +48,11 @@ RENDERDOC_API_1_1_2 *rdoc_api = NULL;
|
|
|
|
|
|
enum user_control { USER_CONTROL_ISO, USER_CONTROL_SHUTTER };
|
|
|
|
|
|
-libmegapixels_devconfig *configuration = { 0 };
|
|
|
-libmegapixels_camera *camera = NULL;
|
|
|
-int current_camera_index = 0;
|
|
|
+mp_state_main state;
|
|
|
|
|
|
static bool camera_is_initialized = false;
|
|
|
struct mp_main_state current_state = { 0 };
|
|
|
|
|
|
-static int preview_width = -1;
|
|
|
-static int preview_height = -1;
|
|
|
-
|
|
|
-static int device_rotation = 0;
|
|
|
-
|
|
|
-static bool gain_is_manual = false;
|
|
|
-static int gain;
|
|
|
-static int gain_max;
|
|
|
-
|
|
|
-static bool exposure_is_manual = false;
|
|
|
-static int exposure;
|
|
|
-
|
|
|
-static bool has_auto_focus_continuous;
|
|
|
-static bool has_auto_focus_start;
|
|
|
-
|
|
|
-static bool flash_enabled = false;
|
|
|
-
|
|
|
static MPProcessPipelineBuffer *current_preview_buffer = NULL;
|
|
|
static int preview_buffer_width = -1;
|
|
|
static int preview_buffer_height = -1;
|
|
@@ -79,8 +61,6 @@ static char last_path[260] = "";
|
|
|
|
|
|
static MPZBarScanResult *zbar_result = NULL;
|
|
|
|
|
|
-static int burst_length = 4;
|
|
|
-
|
|
|
// Widgets
|
|
|
GtkWidget *preview;
|
|
|
GtkWidget *main_stack;
|
|
@@ -117,22 +97,21 @@ static void
|
|
|
update_io_pipeline()
|
|
|
{
|
|
|
struct mp_io_pipeline_state io_state = {
|
|
|
- .camera = camera,
|
|
|
- .burst_length = burst_length,
|
|
|
- .preview_width = preview_width,
|
|
|
- .preview_height = preview_height,
|
|
|
- .device_rotation = device_rotation,
|
|
|
- .gain_is_manual = gain_is_manual,
|
|
|
- .gain = gain,
|
|
|
- .exposure_is_manual = exposure_is_manual,
|
|
|
- .exposure = exposure,
|
|
|
- .flash_enabled = flash_enabled,
|
|
|
+ .camera = state.camera,
|
|
|
+ .burst_length = state.burst_length,
|
|
|
+ .preview_width = state.preview_width,
|
|
|
+ .preview_height = state.preview_height,
|
|
|
+ .device_rotation = state.device_rotation,
|
|
|
+ .gain_is_manual = state.gain_is_manual,
|
|
|
+ .gain = state.gain,
|
|
|
+ .exposure_is_manual = state.exposure_is_manual,
|
|
|
+ .exposure = state.exposure,
|
|
|
+ .flash_enabled = state.flash_enabled,
|
|
|
};
|
|
|
mp_io_pipeline_update_state(&io_state);
|
|
|
|
|
|
// Make the right settings available for the camera
|
|
|
- // TODO: Implement flash again
|
|
|
- gtk_widget_set_visible(flash_button, false);
|
|
|
+ gtk_widget_set_visible(flash_button, state.flash_enabled);
|
|
|
}
|
|
|
|
|
|
static bool
|
|
@@ -145,13 +124,13 @@ update_state(const struct mp_main_state *state)
|
|
|
if (current_state.camera == state->camera) {
|
|
|
current_state.mode = state->mode;
|
|
|
|
|
|
- if (!gain_is_manual) {
|
|
|
- gain = state->gain;
|
|
|
+ if (!state.gain_is_manual) {
|
|
|
+ state.gain = state->gain;
|
|
|
}
|
|
|
- gain_max = state->gain_max;
|
|
|
+ state.gain_max = state->gain_max;
|
|
|
|
|
|
- if (!exposure_is_manual) {
|
|
|
- exposure = state->exposure;
|
|
|
+ if (!state.exposure_is_manual) {
|
|
|
+ state.exposure = state->exposure;
|
|
|
}
|
|
|
|
|
|
has_auto_focus_continuous = state->has_auto_focus_continuous;
|
|
@@ -328,7 +307,7 @@ static void
|
|
|
position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y)
|
|
|
{
|
|
|
int buffer_width, buffer_height;
|
|
|
- if (device_rotation == 0 || device_rotation == 180) {
|
|
|
+ if (state.device_rotation == 0 || state.device_rotation == 180) {
|
|
|
buffer_width = preview_buffer_width;
|
|
|
buffer_height = preview_buffer_height;
|
|
|
} else {
|
|
@@ -341,18 +320,18 @@ position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y)
|
|
|
gtk_widget_get_allocated_height(preview_top_box) * scale_factor;
|
|
|
int bottom_height =
|
|
|
gtk_widget_get_allocated_height(preview_bottom_box) * scale_factor;
|
|
|
- int inner_height = preview_height - top_height - bottom_height;
|
|
|
+ int inner_height = state.preview_height - top_height - bottom_height;
|
|
|
|
|
|
- double scale = MIN(preview_width / (float)buffer_width,
|
|
|
- preview_height / (float)buffer_height);
|
|
|
+ double scale = MIN(state.preview_width / (float)buffer_width,
|
|
|
+ state.preview_height / (float)buffer_height);
|
|
|
|
|
|
*size_x = scale * buffer_width;
|
|
|
*size_y = scale * buffer_height;
|
|
|
|
|
|
- *offset_x = (preview_width - *size_x) / 2.0;
|
|
|
+ *offset_x = (state.preview_width - *size_x) / 2.0;
|
|
|
|
|
|
if (*size_y > inner_height) {
|
|
|
- *offset_y = (preview_height - *size_y) / 2.0;
|
|
|
+ *offset_y = (state.preview_height - *size_y) / 2.0;
|
|
|
} else {
|
|
|
*offset_y = top_height + (inner_height - *size_y) / 2.0;
|
|
|
}
|
|
@@ -380,13 +359,14 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
|
|
|
|
|
|
float offset_x, offset_y, size_x, size_y;
|
|
|
position_preview(&offset_x, &offset_y, &size_x, &size_y);
|
|
|
- glViewport(offset_x, preview_height - size_y - offset_y, size_x, size_y);
|
|
|
+ glViewport(
|
|
|
+ offset_x, state.preview_height - size_y - offset_y, size_x, size_y);
|
|
|
|
|
|
if (current_preview_buffer) {
|
|
|
glUseProgram(blit_program);
|
|
|
|
|
|
GLfloat rotation_list[4] = { 0, -1, 0, 1 };
|
|
|
- int rotation_index = device_rotation / 90;
|
|
|
+ int rotation_index = state.device_rotation / 90;
|
|
|
|
|
|
GLfloat sin_rot = rotation_list[rotation_index];
|
|
|
GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4];
|
|
@@ -493,9 +473,9 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
|
|
|
static gboolean
|
|
|
preview_resize(GtkWidget *widget, int width, int height, gpointer data)
|
|
|
{
|
|
|
- if (preview_width != width || preview_height != height) {
|
|
|
- preview_width = width;
|
|
|
- preview_height = height;
|
|
|
+ if (state.preview_width != width || state.preview_height != height) {
|
|
|
+ state.preview_width = width;
|
|
|
+ state.preview_height = height;
|
|
|
update_io_pipeline();
|
|
|
}
|
|
|
|
|
@@ -689,7 +669,7 @@ preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y)
|
|
|
}
|
|
|
|
|
|
// Tapped preview image itself, try focussing
|
|
|
- if (has_auto_focus_start) {
|
|
|
+ if (state.has_auto_focus_start) {
|
|
|
mp_io_pipeline_focus();
|
|
|
}
|
|
|
}
|
|
@@ -697,11 +677,14 @@ preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y)
|
|
|
static void
|
|
|
run_camera_switch_action(GSimpleAction *action, GVariant *param, gpointer user_data)
|
|
|
{
|
|
|
- current_camera_index++;
|
|
|
- if (current_camera_index > configuration->count) {
|
|
|
- current_camera_index = 0;
|
|
|
+ int new_index = state.camera->index + 1;
|
|
|
+ if (new_index > state.configuration->count) {
|
|
|
+ new_index = 0;
|
|
|
}
|
|
|
- camera = configuration->cameras[current_camera_index];
|
|
|
+
|
|
|
+ state.camera = state.configuration->cameras[new_index];
|
|
|
+ // TODO: allow setting burst length in the config
|
|
|
+ state.burst_length = 5;
|
|
|
update_io_pipeline();
|
|
|
}
|
|
|
|
|
@@ -796,8 +779,8 @@ open_controls(GtkWidget *parent,
|
|
|
static void
|
|
|
set_gain(double value)
|
|
|
{
|
|
|
- if (gain != (int)value) {
|
|
|
- gain = value;
|
|
|
+ if (state.gain != (int)value) {
|
|
|
+ state.gain = value;
|
|
|
update_io_pipeline();
|
|
|
}
|
|
|
}
|
|
@@ -805,8 +788,8 @@ set_gain(double value)
|
|
|
static void
|
|
|
set_gain_auto(bool is_auto)
|
|
|
{
|
|
|
- if (gain_is_manual != !is_auto) {
|
|
|
- gain_is_manual = !is_auto;
|
|
|
+ if (state.gain_is_manual != !is_auto) {
|
|
|
+ state.gain_is_manual = !is_auto;
|
|
|
update_io_pipeline();
|
|
|
}
|
|
|
}
|
|
@@ -817,9 +800,9 @@ open_iso_controls(GtkWidget *button, gpointer user_data)
|
|
|
open_controls(button,
|
|
|
"ISO",
|
|
|
0,
|
|
|
- gain_max,
|
|
|
- gain,
|
|
|
- !gain_is_manual,
|
|
|
+ state.gain_max,
|
|
|
+ state.gain,
|
|
|
+ !state.gain_is_manual,
|
|
|
set_gain,
|
|
|
set_gain_auto);
|
|
|
}
|
|
@@ -840,8 +823,8 @@ set_shutter(double value)
|
|
|
static void
|
|
|
set_shutter_auto(bool is_auto)
|
|
|
{
|
|
|
- if (exposure_is_manual != !is_auto) {
|
|
|
- exposure_is_manual = !is_auto;
|
|
|
+ if (state.exposure_is_manual != !is_auto) {
|
|
|
+ state.exposure_is_manual = !is_auto;
|
|
|
update_io_pipeline();
|
|
|
}
|
|
|
}
|
|
@@ -853,8 +836,8 @@ open_shutter_controls(GtkWidget *button, gpointer user_data)
|
|
|
"Shutter",
|
|
|
1.0,
|
|
|
360.0,
|
|
|
- exposure,
|
|
|
- !exposure_is_manual,
|
|
|
+ state.exposure,
|
|
|
+ !state.exposure_is_manual,
|
|
|
set_shutter,
|
|
|
set_shutter_auto);
|
|
|
}
|
|
@@ -862,11 +845,11 @@ open_shutter_controls(GtkWidget *button, gpointer user_data)
|
|
|
static void
|
|
|
flash_button_clicked(GtkWidget *button, gpointer user_data)
|
|
|
{
|
|
|
- flash_enabled = !flash_enabled;
|
|
|
+ state.flash_enabled = !state.flash_enabled;
|
|
|
update_io_pipeline();
|
|
|
|
|
|
const char *icon_name =
|
|
|
- flash_enabled ? "flash-enabled-symbolic" : "flash-disabled-symbolic";
|
|
|
+ state.flash_enabled ? "flash-enabled-symbolic" : "flash-disabled-symbolic";
|
|
|
gtk_button_set_icon_name(GTK_BUTTON(button), icon_name);
|
|
|
}
|
|
|
|
|
@@ -876,8 +859,7 @@ on_realize(GtkWidget *window, gpointer *data)
|
|
|
GtkNative *native = gtk_widget_get_native(window);
|
|
|
mp_process_pipeline_init_gl(gtk_native_get_surface(native));
|
|
|
|
|
|
- current_camera_index = 0;
|
|
|
- camera = configuration->cameras[0];
|
|
|
+ state.camera = state.configuration->cameras[0];
|
|
|
update_io_pipeline();
|
|
|
}
|
|
|
|
|
@@ -893,7 +875,7 @@ create_simple_action(GtkApplication *app, const char *name, GCallback callback)
|
|
|
static void
|
|
|
update_ui_rotation()
|
|
|
{
|
|
|
- if (device_rotation == 0 || device_rotation == 180) {
|
|
|
+ if (state.device_rotation == 0 || state.device_rotation == 180) {
|
|
|
// Portrait
|
|
|
gtk_widget_set_halign(preview_top_box, GTK_ALIGN_FILL);
|
|
|
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box),
|
|
@@ -903,7 +885,7 @@ update_ui_rotation()
|
|
|
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box),
|
|
|
GTK_ORIENTATION_HORIZONTAL);
|
|
|
|
|
|
- if (device_rotation == 0) {
|
|
|
+ if (state.device_rotation == 0) {
|
|
|
gtk_widget_set_valign(preview_top_box, GTK_ALIGN_START);
|
|
|
gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_END);
|
|
|
} else {
|
|
@@ -920,7 +902,7 @@ update_ui_rotation()
|
|
|
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box),
|
|
|
GTK_ORIENTATION_VERTICAL);
|
|
|
|
|
|
- if (device_rotation == 90) {
|
|
|
+ if (state.device_rotation == 90) {
|
|
|
gtk_widget_set_halign(preview_top_box, GTK_ALIGN_END);
|
|
|
gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_START);
|
|
|
} else {
|
|
@@ -1036,8 +1018,8 @@ wl_handle_geometry(void *data,
|
|
|
assert(transform < 4);
|
|
|
int new_rotation = transform * 90;
|
|
|
|
|
|
- if (new_rotation != device_rotation) {
|
|
|
- device_rotation = new_rotation;
|
|
|
+ if (new_rotation != state.device_rotation) {
|
|
|
+ state.device_rotation = new_rotation;
|
|
|
update_io_pipeline();
|
|
|
update_ui_rotation();
|
|
|
}
|
|
@@ -1110,8 +1092,8 @@ xevent_handler(GdkDisplay *display, XEvent *xevent, gpointer data)
|
|
|
new_rotation = 270;
|
|
|
break;
|
|
|
}
|
|
|
- if (new_rotation != device_rotation) {
|
|
|
- device_rotation = new_rotation;
|
|
|
+ if (new_rotation != state.device_rotation) {
|
|
|
+ state.device_rotation = new_rotation;
|
|
|
update_io_pipeline();
|
|
|
update_ui_rotation();
|
|
|
}
|
|
@@ -1281,8 +1263,8 @@ activate(GtkApplication *app, gpointer data)
|
|
|
new_rotation = 270;
|
|
|
break;
|
|
|
}
|
|
|
- if (new_rotation != device_rotation) {
|
|
|
- device_rotation = new_rotation;
|
|
|
+ if (new_rotation != state.device_rotation) {
|
|
|
+ state.device_rotation = new_rotation;
|
|
|
update_ui_rotation();
|
|
|
}
|
|
|
}
|
|
@@ -1342,14 +1324,14 @@ main(int argc, char *argv[])
|
|
|
}
|
|
|
#endif
|
|
|
char configfile[PATH_MAX];
|
|
|
- libmegapixels_init(&configuration);
|
|
|
+ libmegapixels_init(&state.configuration);
|
|
|
if (libmegapixels_find_config(configfile)) {
|
|
|
- if (!libmegapixels_load_file(configuration, configfile)) {
|
|
|
+ if (!libmegapixels_load_file(state.configuration, configfile)) {
|
|
|
fprintf(stderr, "Could not load config\n");
|
|
|
return 1;
|
|
|
}
|
|
|
} else {
|
|
|
- if (!libmegapixels_load_uvc(configuration)) {
|
|
|
+ if (!libmegapixels_load_uvc(state.configuration)) {
|
|
|
fprintf(stderr, "No config found\n");
|
|
|
return 1;
|
|
|
}
|