WIP
This commit is contained in:
@@ -75,7 +75,7 @@ add_custom_target(
|
|||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB srcs src/*.c src/*h)
|
file(GLOB srcs src/*.c src/*h)
|
||||||
add_executable(megapixels-gtk ${srcs} ${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C})
|
add_executable(megapixels-gtk ${srcs} ${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C} src/state.h)
|
||||||
set_source_files_properties(
|
set_source_files_properties(
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C}
|
${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C}
|
||||||
PROPERTIES GENERATED TRUE
|
PROPERTIES GENERATED TRUE
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
project('megapixels', 'c', version: '1.6.1')
|
project('megapixels', 'c', version: '2.0.0')
|
||||||
|
|
||||||
gnome = import('gnome')
|
gnome = import('gnome')
|
||||||
gtkdep = dependency('gtk4')
|
gtkdep = dependency('gtk4')
|
||||||
|
146
src/main.c
146
src/main.c
@@ -4,6 +4,7 @@
|
|||||||
#include "gl_util.h"
|
#include "gl_util.h"
|
||||||
#include "io_pipeline.h"
|
#include "io_pipeline.h"
|
||||||
#include "process_pipeline.h"
|
#include "process_pipeline.h"
|
||||||
|
#include "state.h"
|
||||||
#include <asm/errno.h>
|
#include <asm/errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.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 };
|
enum user_control { USER_CONTROL_ISO, USER_CONTROL_SHUTTER };
|
||||||
|
|
||||||
libmegapixels_devconfig *configuration = { 0 };
|
mp_state_main state;
|
||||||
libmegapixels_camera *camera = NULL;
|
|
||||||
int current_camera_index = 0;
|
|
||||||
|
|
||||||
static bool camera_is_initialized = false;
|
static bool camera_is_initialized = false;
|
||||||
struct mp_main_state current_state = { 0 };
|
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 MPProcessPipelineBuffer *current_preview_buffer = NULL;
|
||||||
static int preview_buffer_width = -1;
|
static int preview_buffer_width = -1;
|
||||||
static int preview_buffer_height = -1;
|
static int preview_buffer_height = -1;
|
||||||
@@ -79,8 +61,6 @@ static char last_path[260] = "";
|
|||||||
|
|
||||||
static MPZBarScanResult *zbar_result = NULL;
|
static MPZBarScanResult *zbar_result = NULL;
|
||||||
|
|
||||||
static int burst_length = 4;
|
|
||||||
|
|
||||||
// Widgets
|
// Widgets
|
||||||
GtkWidget *preview;
|
GtkWidget *preview;
|
||||||
GtkWidget *main_stack;
|
GtkWidget *main_stack;
|
||||||
@@ -117,22 +97,21 @@ static void
|
|||||||
update_io_pipeline()
|
update_io_pipeline()
|
||||||
{
|
{
|
||||||
struct mp_io_pipeline_state io_state = {
|
struct mp_io_pipeline_state io_state = {
|
||||||
.camera = camera,
|
.camera = state.camera,
|
||||||
.burst_length = burst_length,
|
.burst_length = state.burst_length,
|
||||||
.preview_width = preview_width,
|
.preview_width = state.preview_width,
|
||||||
.preview_height = preview_height,
|
.preview_height = state.preview_height,
|
||||||
.device_rotation = device_rotation,
|
.device_rotation = state.device_rotation,
|
||||||
.gain_is_manual = gain_is_manual,
|
.gain_is_manual = state.gain_is_manual,
|
||||||
.gain = gain,
|
.gain = state.gain,
|
||||||
.exposure_is_manual = exposure_is_manual,
|
.exposure_is_manual = state.exposure_is_manual,
|
||||||
.exposure = exposure,
|
.exposure = state.exposure,
|
||||||
.flash_enabled = flash_enabled,
|
.flash_enabled = state.flash_enabled,
|
||||||
};
|
};
|
||||||
mp_io_pipeline_update_state(&io_state);
|
mp_io_pipeline_update_state(&io_state);
|
||||||
|
|
||||||
// Make the right settings available for the camera
|
// Make the right settings available for the camera
|
||||||
// TODO: Implement flash again
|
gtk_widget_set_visible(flash_button, state.flash_enabled);
|
||||||
gtk_widget_set_visible(flash_button, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -145,13 +124,13 @@ update_state(const struct mp_main_state *state)
|
|||||||
if (current_state.camera == state->camera) {
|
if (current_state.camera == state->camera) {
|
||||||
current_state.mode = state->mode;
|
current_state.mode = state->mode;
|
||||||
|
|
||||||
if (!gain_is_manual) {
|
if (!state.gain_is_manual) {
|
||||||
gain = state->gain;
|
state.gain = state->gain;
|
||||||
}
|
}
|
||||||
gain_max = state->gain_max;
|
state.gain_max = state->gain_max;
|
||||||
|
|
||||||
if (!exposure_is_manual) {
|
if (!state.exposure_is_manual) {
|
||||||
exposure = state->exposure;
|
state.exposure = state->exposure;
|
||||||
}
|
}
|
||||||
|
|
||||||
has_auto_focus_continuous = state->has_auto_focus_continuous;
|
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)
|
position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y)
|
||||||
{
|
{
|
||||||
int buffer_width, buffer_height;
|
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_width = preview_buffer_width;
|
||||||
buffer_height = preview_buffer_height;
|
buffer_height = preview_buffer_height;
|
||||||
} else {
|
} 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;
|
gtk_widget_get_allocated_height(preview_top_box) * scale_factor;
|
||||||
int bottom_height =
|
int bottom_height =
|
||||||
gtk_widget_get_allocated_height(preview_bottom_box) * scale_factor;
|
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,
|
double scale = MIN(state.preview_width / (float)buffer_width,
|
||||||
preview_height / (float)buffer_height);
|
state.preview_height / (float)buffer_height);
|
||||||
|
|
||||||
*size_x = scale * buffer_width;
|
*size_x = scale * buffer_width;
|
||||||
*size_y = scale * buffer_height;
|
*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) {
|
if (*size_y > inner_height) {
|
||||||
*offset_y = (preview_height - *size_y) / 2.0;
|
*offset_y = (state.preview_height - *size_y) / 2.0;
|
||||||
} else {
|
} else {
|
||||||
*offset_y = top_height + (inner_height - *size_y) / 2.0;
|
*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;
|
float offset_x, offset_y, size_x, size_y;
|
||||||
position_preview(&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) {
|
if (current_preview_buffer) {
|
||||||
glUseProgram(blit_program);
|
glUseProgram(blit_program);
|
||||||
|
|
||||||
GLfloat rotation_list[4] = { 0, -1, 0, 1 };
|
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 sin_rot = rotation_list[rotation_index];
|
||||||
GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4];
|
GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4];
|
||||||
@@ -493,9 +473,9 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
|
|||||||
static gboolean
|
static gboolean
|
||||||
preview_resize(GtkWidget *widget, int width, int height, gpointer data)
|
preview_resize(GtkWidget *widget, int width, int height, gpointer data)
|
||||||
{
|
{
|
||||||
if (preview_width != width || preview_height != height) {
|
if (state.preview_width != width || state.preview_height != height) {
|
||||||
preview_width = width;
|
state.preview_width = width;
|
||||||
preview_height = height;
|
state.preview_height = height;
|
||||||
update_io_pipeline();
|
update_io_pipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -689,7 +669,7 @@ preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tapped preview image itself, try focussing
|
// Tapped preview image itself, try focussing
|
||||||
if (has_auto_focus_start) {
|
if (state.has_auto_focus_start) {
|
||||||
mp_io_pipeline_focus();
|
mp_io_pipeline_focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -697,11 +677,14 @@ preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y)
|
|||||||
static void
|
static void
|
||||||
run_camera_switch_action(GSimpleAction *action, GVariant *param, gpointer user_data)
|
run_camera_switch_action(GSimpleAction *action, GVariant *param, gpointer user_data)
|
||||||
{
|
{
|
||||||
current_camera_index++;
|
int new_index = state.camera->index + 1;
|
||||||
if (current_camera_index > configuration->count) {
|
if (new_index > state.configuration->count) {
|
||||||
current_camera_index = 0;
|
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();
|
update_io_pipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,8 +779,8 @@ open_controls(GtkWidget *parent,
|
|||||||
static void
|
static void
|
||||||
set_gain(double value)
|
set_gain(double value)
|
||||||
{
|
{
|
||||||
if (gain != (int)value) {
|
if (state.gain != (int)value) {
|
||||||
gain = value;
|
state.gain = value;
|
||||||
update_io_pipeline();
|
update_io_pipeline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -805,8 +788,8 @@ set_gain(double value)
|
|||||||
static void
|
static void
|
||||||
set_gain_auto(bool is_auto)
|
set_gain_auto(bool is_auto)
|
||||||
{
|
{
|
||||||
if (gain_is_manual != !is_auto) {
|
if (state.gain_is_manual != !is_auto) {
|
||||||
gain_is_manual = !is_auto;
|
state.gain_is_manual = !is_auto;
|
||||||
update_io_pipeline();
|
update_io_pipeline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -817,9 +800,9 @@ open_iso_controls(GtkWidget *button, gpointer user_data)
|
|||||||
open_controls(button,
|
open_controls(button,
|
||||||
"ISO",
|
"ISO",
|
||||||
0,
|
0,
|
||||||
gain_max,
|
state.gain_max,
|
||||||
gain,
|
state.gain,
|
||||||
!gain_is_manual,
|
!state.gain_is_manual,
|
||||||
set_gain,
|
set_gain,
|
||||||
set_gain_auto);
|
set_gain_auto);
|
||||||
}
|
}
|
||||||
@@ -840,8 +823,8 @@ set_shutter(double value)
|
|||||||
static void
|
static void
|
||||||
set_shutter_auto(bool is_auto)
|
set_shutter_auto(bool is_auto)
|
||||||
{
|
{
|
||||||
if (exposure_is_manual != !is_auto) {
|
if (state.exposure_is_manual != !is_auto) {
|
||||||
exposure_is_manual = !is_auto;
|
state.exposure_is_manual = !is_auto;
|
||||||
update_io_pipeline();
|
update_io_pipeline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -853,8 +836,8 @@ open_shutter_controls(GtkWidget *button, gpointer user_data)
|
|||||||
"Shutter",
|
"Shutter",
|
||||||
1.0,
|
1.0,
|
||||||
360.0,
|
360.0,
|
||||||
exposure,
|
state.exposure,
|
||||||
!exposure_is_manual,
|
!state.exposure_is_manual,
|
||||||
set_shutter,
|
set_shutter,
|
||||||
set_shutter_auto);
|
set_shutter_auto);
|
||||||
}
|
}
|
||||||
@@ -862,11 +845,11 @@ open_shutter_controls(GtkWidget *button, gpointer user_data)
|
|||||||
static void
|
static void
|
||||||
flash_button_clicked(GtkWidget *button, gpointer user_data)
|
flash_button_clicked(GtkWidget *button, gpointer user_data)
|
||||||
{
|
{
|
||||||
flash_enabled = !flash_enabled;
|
state.flash_enabled = !state.flash_enabled;
|
||||||
update_io_pipeline();
|
update_io_pipeline();
|
||||||
|
|
||||||
const char *icon_name =
|
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);
|
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);
|
GtkNative *native = gtk_widget_get_native(window);
|
||||||
mp_process_pipeline_init_gl(gtk_native_get_surface(native));
|
mp_process_pipeline_init_gl(gtk_native_get_surface(native));
|
||||||
|
|
||||||
current_camera_index = 0;
|
state.camera = state.configuration->cameras[0];
|
||||||
camera = configuration->cameras[0];
|
|
||||||
update_io_pipeline();
|
update_io_pipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,7 +875,7 @@ create_simple_action(GtkApplication *app, const char *name, GCallback callback)
|
|||||||
static void
|
static void
|
||||||
update_ui_rotation()
|
update_ui_rotation()
|
||||||
{
|
{
|
||||||
if (device_rotation == 0 || device_rotation == 180) {
|
if (state.device_rotation == 0 || state.device_rotation == 180) {
|
||||||
// Portrait
|
// Portrait
|
||||||
gtk_widget_set_halign(preview_top_box, GTK_ALIGN_FILL);
|
gtk_widget_set_halign(preview_top_box, GTK_ALIGN_FILL);
|
||||||
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box),
|
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_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box),
|
||||||
GTK_ORIENTATION_HORIZONTAL);
|
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_top_box, GTK_ALIGN_START);
|
||||||
gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_END);
|
gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_END);
|
||||||
} else {
|
} else {
|
||||||
@@ -920,7 +902,7 @@ update_ui_rotation()
|
|||||||
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box),
|
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box),
|
||||||
GTK_ORIENTATION_VERTICAL);
|
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_top_box, GTK_ALIGN_END);
|
||||||
gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_START);
|
gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_START);
|
||||||
} else {
|
} else {
|
||||||
@@ -1036,8 +1018,8 @@ wl_handle_geometry(void *data,
|
|||||||
assert(transform < 4);
|
assert(transform < 4);
|
||||||
int new_rotation = transform * 90;
|
int new_rotation = transform * 90;
|
||||||
|
|
||||||
if (new_rotation != device_rotation) {
|
if (new_rotation != state.device_rotation) {
|
||||||
device_rotation = new_rotation;
|
state.device_rotation = new_rotation;
|
||||||
update_io_pipeline();
|
update_io_pipeline();
|
||||||
update_ui_rotation();
|
update_ui_rotation();
|
||||||
}
|
}
|
||||||
@@ -1110,8 +1092,8 @@ xevent_handler(GdkDisplay *display, XEvent *xevent, gpointer data)
|
|||||||
new_rotation = 270;
|
new_rotation = 270;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (new_rotation != device_rotation) {
|
if (new_rotation != state.device_rotation) {
|
||||||
device_rotation = new_rotation;
|
state.device_rotation = new_rotation;
|
||||||
update_io_pipeline();
|
update_io_pipeline();
|
||||||
update_ui_rotation();
|
update_ui_rotation();
|
||||||
}
|
}
|
||||||
@@ -1281,8 +1263,8 @@ activate(GtkApplication *app, gpointer data)
|
|||||||
new_rotation = 270;
|
new_rotation = 270;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (new_rotation != device_rotation) {
|
if (new_rotation != state.device_rotation) {
|
||||||
device_rotation = new_rotation;
|
state.device_rotation = new_rotation;
|
||||||
update_ui_rotation();
|
update_ui_rotation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1342,14 +1324,14 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
char configfile[PATH_MAX];
|
char configfile[PATH_MAX];
|
||||||
libmegapixels_init(&configuration);
|
libmegapixels_init(&state.configuration);
|
||||||
if (libmegapixels_find_config(configfile)) {
|
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");
|
fprintf(stderr, "Could not load config\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!libmegapixels_load_uvc(configuration)) {
|
if (!libmegapixels_load_uvc(state.configuration)) {
|
||||||
fprintf(stderr, "No config found\n");
|
fprintf(stderr, "No config found\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
26
src/state.h
Normal file
26
src/state.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include <libmegapixels.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct state_main {
|
||||||
|
libmegapixels_devconfig *configuration;
|
||||||
|
libmegapixels_camera *camera;
|
||||||
|
|
||||||
|
int preview_width;
|
||||||
|
int preview_height;
|
||||||
|
int device_rotation;
|
||||||
|
|
||||||
|
int burst_length;
|
||||||
|
|
||||||
|
// Control state
|
||||||
|
bool gain_is_manual;
|
||||||
|
int gain;
|
||||||
|
int gain_max;
|
||||||
|
|
||||||
|
bool exposure_is_manual;
|
||||||
|
int exposure;
|
||||||
|
|
||||||
|
bool flash_enabled;
|
||||||
|
|
||||||
|
bool has_auto_focus_continuous;
|
||||||
|
bool has_auto_focus_start;
|
||||||
|
} mp_state_main;
|
Reference in New Issue
Block a user