Preview rotation follows device
This commit is contained in:
parent
46bfb39dfd
commit
64b75bcbe5
|
@ -5,10 +5,12 @@ precision mediump float;
|
||||||
attribute vec2 vert;
|
attribute vec2 vert;
|
||||||
attribute vec2 tex_coord;
|
attribute vec2 tex_coord;
|
||||||
|
|
||||||
|
uniform mat3 transform;
|
||||||
|
|
||||||
varying vec2 uv;
|
varying vec2 uv;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
uv = tex_coord;
|
uv = tex_coord;
|
||||||
|
|
||||||
gl_Position = vec4(vert, 0, 1);
|
gl_Position = vec4(transform * vec3(vert, 1), 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,8 @@ static int captures_remaining = 0;
|
||||||
static int preview_width;
|
static int preview_width;
|
||||||
static int preview_height;
|
static int preview_height;
|
||||||
|
|
||||||
|
static int device_rotation;
|
||||||
|
|
||||||
struct control_state {
|
struct control_state {
|
||||||
bool gain_is_manual;
|
bool gain_is_manual;
|
||||||
int gain;
|
int gain;
|
||||||
|
@ -275,6 +277,7 @@ update_process_pipeline()
|
||||||
.burst_length = burst_length,
|
.burst_length = burst_length,
|
||||||
.preview_width = preview_width,
|
.preview_width = preview_width,
|
||||||
.preview_height = preview_height,
|
.preview_height = preview_height,
|
||||||
|
.device_rotation = device_rotation,
|
||||||
.gain_is_manual = current_controls.gain_is_manual,
|
.gain_is_manual = current_controls.gain_is_manual,
|
||||||
.gain = current_controls.gain,
|
.gain = current_controls.gain,
|
||||||
.gain_max = info->gain_max,
|
.gain_max = info->gain_max,
|
||||||
|
@ -521,11 +524,13 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
|
||||||
|
|
||||||
has_changed = has_changed || burst_length != state->burst_length ||
|
has_changed = has_changed || burst_length != state->burst_length ||
|
||||||
preview_width != state->preview_width ||
|
preview_width != state->preview_width ||
|
||||||
preview_height != state->preview_height;
|
preview_height != state->preview_height ||
|
||||||
|
device_rotation != state->device_rotation;
|
||||||
|
|
||||||
burst_length = state->burst_length;
|
burst_length = state->burst_length;
|
||||||
preview_width = state->preview_width;
|
preview_width = state->preview_width;
|
||||||
preview_height = state->preview_height;
|
preview_height = state->preview_height;
|
||||||
|
device_rotation = state->device_rotation;
|
||||||
|
|
||||||
if (camera) {
|
if (camera) {
|
||||||
struct control_state previous_desired = desired_controls;
|
struct control_state previous_desired = desired_controls;
|
||||||
|
|
|
@ -10,6 +10,8 @@ struct mp_io_pipeline_state {
|
||||||
int preview_width;
|
int preview_width;
|
||||||
int preview_height;
|
int preview_height;
|
||||||
|
|
||||||
|
int device_rotation;
|
||||||
|
|
||||||
bool gain_is_manual;
|
bool gain_is_manual;
|
||||||
int gain;
|
int gain;
|
||||||
|
|
||||||
|
|
114
src/main.c
114
src/main.c
|
@ -40,6 +40,8 @@ static MPCameraMode mode;
|
||||||
static int preview_width = -1;
|
static int preview_width = -1;
|
||||||
static int preview_height = -1;
|
static int preview_height = -1;
|
||||||
|
|
||||||
|
static int device_rotation = 0;
|
||||||
|
|
||||||
static bool gain_is_manual = false;
|
static bool gain_is_manual = false;
|
||||||
static int gain;
|
static int gain;
|
||||||
static int gain_max;
|
static int gain_max;
|
||||||
|
@ -95,6 +97,7 @@ update_io_pipeline()
|
||||||
.burst_length = burst_length,
|
.burst_length = burst_length,
|
||||||
.preview_width = preview_width,
|
.preview_width = preview_width,
|
||||||
.preview_height = preview_height,
|
.preview_height = preview_height,
|
||||||
|
.device_rotation = device_rotation,
|
||||||
.gain_is_manual = gain_is_manual,
|
.gain_is_manual = gain_is_manual,
|
||||||
.gain = gain,
|
.gain = gain,
|
||||||
.exposure_is_manual = exposure_is_manual,
|
.exposure_is_manual = exposure_is_manual,
|
||||||
|
@ -215,6 +218,7 @@ mp_main_capture_completed(GdkTexture *thumb, const char *fname)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLuint blit_program;
|
static GLuint blit_program;
|
||||||
|
static GLuint blit_uniform_transform;
|
||||||
static GLuint blit_uniform_texture;
|
static GLuint blit_uniform_texture;
|
||||||
static GLuint solid_program;
|
static GLuint solid_program;
|
||||||
static GLuint solid_uniform_color;
|
static GLuint solid_uniform_color;
|
||||||
|
@ -247,6 +251,7 @@ preview_realize(GtkGLArea *area)
|
||||||
glBindAttribLocation(blit_program, GL_UTIL_TEX_COORD_ATTRIBUTE, "tex_coord");
|
glBindAttribLocation(blit_program, GL_UTIL_TEX_COORD_ATTRIBUTE, "tex_coord");
|
||||||
check_gl();
|
check_gl();
|
||||||
|
|
||||||
|
blit_uniform_transform = glGetUniformLocation(blit_program, "transform");
|
||||||
blit_uniform_texture = glGetUniformLocation(blit_program, "texture");
|
blit_uniform_texture = glGetUniformLocation(blit_program, "texture");
|
||||||
|
|
||||||
GLuint solid_shaders[] = {
|
GLuint solid_shaders[] = {
|
||||||
|
@ -266,17 +271,26 @@ preview_realize(GtkGLArea *area)
|
||||||
static void
|
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 scale = gtk_widget_get_scale_factor(preview);
|
int buffer_width, buffer_height;
|
||||||
int preview_height = gtk_widget_get_allocated_height(preview) * scale;
|
if (device_rotation == 0 || device_rotation == 180) {
|
||||||
int top_height = gtk_widget_get_allocated_height(preview_top_box) * scale;
|
buffer_width = preview_buffer_width;
|
||||||
int bottom_height = gtk_widget_get_allocated_height(preview_bottom_box) * scale;
|
buffer_height = preview_buffer_height;
|
||||||
|
} else {
|
||||||
|
buffer_width = preview_buffer_height;
|
||||||
|
buffer_height = preview_buffer_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scale_factor = gtk_widget_get_scale_factor(preview);
|
||||||
|
int top_height = 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 = preview_height - top_height - bottom_height;
|
||||||
|
|
||||||
double ratio = preview_buffer_height / (double)preview_buffer_width;
|
double scale = MIN(preview_width / (float) buffer_width, preview_height / (float) buffer_height);
|
||||||
|
|
||||||
*offset_x = 0;
|
*size_x = scale * buffer_width;
|
||||||
*size_x = preview_width;
|
*size_y = scale * buffer_height;
|
||||||
*size_y = preview_width * ratio;
|
|
||||||
|
*offset_x = (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 = (preview_height - *size_y) / 2.0;
|
||||||
|
@ -314,6 +328,19 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
|
||||||
if (current_preview_buffer) {
|
if (current_preview_buffer) {
|
||||||
glUseProgram(blit_program);
|
glUseProgram(blit_program);
|
||||||
|
|
||||||
|
GLfloat rotation_list[4] = { 0, -1, 0, 1 };
|
||||||
|
int rotation_index = device_rotation / 90;
|
||||||
|
|
||||||
|
GLfloat sin_rot = rotation_list[rotation_index];
|
||||||
|
GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4];
|
||||||
|
GLfloat matrix[9] = {
|
||||||
|
cos_rot, sin_rot, 0,
|
||||||
|
-sin_rot, cos_rot, 0,
|
||||||
|
0, 0, 1,
|
||||||
|
};
|
||||||
|
glUniformMatrix3fv(blit_uniform_transform, 1, GL_FALSE, matrix);
|
||||||
|
check_gl();
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, mp_process_pipeline_buffer_get_texture_id(current_preview_buffer));
|
glBindTexture(GL_TEXTURE_2D, mp_process_pipeline_buffer_get_texture_id(current_preview_buffer));
|
||||||
glUniform1i(blit_uniform_texture, 0);
|
glUniform1i(blit_uniform_texture, 0);
|
||||||
|
@ -719,6 +746,62 @@ create_simple_action(GtkApplication *app, const char *name, GCallback callback)
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void display_config_received(GDBusConnection *conn, GAsyncResult *res, gpointer user_data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GVariant *result = g_dbus_connection_call_finish(conn, res, &error);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
printf("Failed to get display configuration: %s\n", error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GVariant *configs = g_variant_get_child_value(result, 1);
|
||||||
|
if (g_variant_n_children(configs) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GVariant *config = g_variant_get_child_value(configs, 0);
|
||||||
|
GVariant *rot_config = g_variant_get_child_value(config, 7);
|
||||||
|
uint32_t rotation_index = g_variant_get_uint32(rot_config);
|
||||||
|
|
||||||
|
assert(rotation_index < 4);
|
||||||
|
int new_rotation = rotation_index * 90;
|
||||||
|
|
||||||
|
if (new_rotation != device_rotation) {
|
||||||
|
device_rotation = new_rotation;
|
||||||
|
update_io_pipeline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_screen_rotation(GDBusConnection *conn)
|
||||||
|
{
|
||||||
|
g_dbus_connection_call(conn,
|
||||||
|
"org.gnome.Mutter.DisplayConfig",
|
||||||
|
"/org/gnome/Mutter/DisplayConfig",
|
||||||
|
"org.gnome.Mutter.DisplayConfig",
|
||||||
|
"GetResources",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NO_AUTO_START,
|
||||||
|
-1,
|
||||||
|
NULL,
|
||||||
|
(GAsyncReadyCallback)display_config_received,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_screen_rotate(
|
||||||
|
GDBusConnection *conn,
|
||||||
|
const gchar *sender_name,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *signal_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
update_screen_rotation(conn);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
activate(GtkApplication *app, gpointer data)
|
activate(GtkApplication *app, gpointer data)
|
||||||
{
|
{
|
||||||
|
@ -779,6 +862,21 @@ activate(GtkApplication *app, gpointer data)
|
||||||
const char *quit_accels[] = { "<Ctrl>q", "<Ctrl>w", NULL };
|
const char *quit_accels[] = { "<Ctrl>q", "<Ctrl>w", NULL };
|
||||||
gtk_application_set_accels_for_action(app, "app.quit", quit_accels);
|
gtk_application_set_accels_for_action(app, "app.quit", quit_accels);
|
||||||
|
|
||||||
|
// Listen for phosh rotation
|
||||||
|
GDBusConnection *conn = g_application_get_dbus_connection(G_APPLICATION(app));
|
||||||
|
g_dbus_connection_signal_subscribe(
|
||||||
|
conn,
|
||||||
|
NULL,
|
||||||
|
"org.gnome.Mutter.DisplayConfig",
|
||||||
|
"MonitorsChanged",
|
||||||
|
"/org/gnome/Mutter/DisplayConfig",
|
||||||
|
NULL,
|
||||||
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||||
|
&on_screen_rotate,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
update_screen_rotation(conn);
|
||||||
|
|
||||||
mp_io_pipeline_start();
|
mp_io_pipeline_start();
|
||||||
|
|
||||||
gtk_application_add_window(app, GTK_WINDOW(window));
|
gtk_application_add_window(app, GTK_WINDOW(window));
|
||||||
|
|
|
@ -31,6 +31,7 @@ static volatile int frames_processed = 0;
|
||||||
static volatile int frames_received = 0;
|
static volatile int frames_received = 0;
|
||||||
|
|
||||||
static const struct mp_camera_config *camera;
|
static const struct mp_camera_config *camera;
|
||||||
|
static int camera_rotation;
|
||||||
|
|
||||||
static MPCameraMode mode;
|
static MPCameraMode mode;
|
||||||
|
|
||||||
|
@ -40,6 +41,8 @@ static int captures_remaining = 0;
|
||||||
static int preview_width;
|
static int preview_width;
|
||||||
static int preview_height;
|
static int preview_height;
|
||||||
|
|
||||||
|
static int device_rotation;
|
||||||
|
|
||||||
static int output_buffer_width = -1;
|
static int output_buffer_width = -1;
|
||||||
static int output_buffer_height = -1;
|
static int output_buffer_height = -1;
|
||||||
|
|
||||||
|
@ -370,13 +373,13 @@ process_image_for_capture(const uint8_t *image, int count)
|
||||||
TIFFSetField(tif, TIFFTAG_MAKE, mp_get_device_make());
|
TIFFSetField(tif, TIFFTAG_MAKE, mp_get_device_make());
|
||||||
TIFFSetField(tif, TIFFTAG_MODEL, mp_get_device_model());
|
TIFFSetField(tif, TIFFTAG_MODEL, mp_get_device_model());
|
||||||
uint16_t orientation;
|
uint16_t orientation;
|
||||||
if (camera->rotate == 0) {
|
if (camera_rotation == 0) {
|
||||||
orientation = camera->mirrored ? ORIENTATION_TOPRIGHT :
|
orientation = camera->mirrored ? ORIENTATION_TOPRIGHT :
|
||||||
ORIENTATION_TOPLEFT;
|
ORIENTATION_TOPLEFT;
|
||||||
} else if (camera->rotate == 90) {
|
} else if (camera_rotation == 90) {
|
||||||
orientation = camera->mirrored ? ORIENTATION_RIGHTBOT :
|
orientation = camera->mirrored ? ORIENTATION_RIGHTBOT :
|
||||||
ORIENTATION_LEFTBOT;
|
ORIENTATION_LEFTBOT;
|
||||||
} else if (camera->rotate == 180) {
|
} else if (camera_rotation == 180) {
|
||||||
orientation = camera->mirrored ? ORIENTATION_BOTLEFT :
|
orientation = camera->mirrored ? ORIENTATION_BOTLEFT :
|
||||||
ORIENTATION_BOTRIGHT;
|
ORIENTATION_BOTRIGHT;
|
||||||
} else {
|
} else {
|
||||||
|
@ -583,7 +586,7 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer)
|
||||||
memcpy(image, buffer->data, size);
|
memcpy(image, buffer->data, size);
|
||||||
mp_io_pipeline_release_buffer(buffer->index);
|
mp_io_pipeline_release_buffer(buffer->index);
|
||||||
|
|
||||||
MPZBarImage *zbar_image = mp_zbar_image_new(image, mode.pixel_format, mode.width, mode.height, camera->rotate, camera->mirrored);
|
MPZBarImage *zbar_image = mp_zbar_image_new(image, mode.pixel_format, mode.width, mode.height, camera_rotation, camera->mirrored);
|
||||||
mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image));
|
mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image));
|
||||||
|
|
||||||
#ifdef PROFILE_PROCESS
|
#ifdef PROFILE_PROCESS
|
||||||
|
@ -692,10 +695,21 @@ on_output_changed()
|
||||||
camera->blacklevel);
|
camera->blacklevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mod(int a, int b)
|
||||||
|
{
|
||||||
|
int r = a % b;
|
||||||
|
return r < 0 ? r + b : r;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state)
|
update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state)
|
||||||
{
|
{
|
||||||
const bool output_changed = (!mp_camera_mode_is_equivalent(&mode, &state->mode) || preview_width != state->preview_width || preview_height != state->preview_height);
|
const bool output_changed =
|
||||||
|
!mp_camera_mode_is_equivalent(&mode, &state->mode)
|
||||||
|
|| preview_width != state->preview_width
|
||||||
|
|| preview_height != state->preview_height
|
||||||
|
|| device_rotation != state->device_rotation;
|
||||||
|
|
||||||
camera = state->camera;
|
camera = state->camera;
|
||||||
mode = state->mode;
|
mode = state->mode;
|
||||||
|
@ -703,6 +717,8 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
|
||||||
preview_width = state->preview_width;
|
preview_width = state->preview_width;
|
||||||
preview_height = state->preview_height;
|
preview_height = state->preview_height;
|
||||||
|
|
||||||
|
device_rotation = state->device_rotation;
|
||||||
|
|
||||||
burst_length = state->burst_length;
|
burst_length = state->burst_length;
|
||||||
|
|
||||||
// gain_is_manual = state->gain_is_manual;
|
// gain_is_manual = state->gain_is_manual;
|
||||||
|
@ -713,6 +729,8 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
|
||||||
exposure = state->exposure;
|
exposure = state->exposure;
|
||||||
|
|
||||||
if (output_changed) {
|
if (output_changed) {
|
||||||
|
camera_rotation = mod(camera->rotate - device_rotation, 360);
|
||||||
|
|
||||||
on_output_changed();
|
on_output_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ struct mp_process_pipeline_state {
|
||||||
int preview_width;
|
int preview_width;
|
||||||
int preview_height;
|
int preview_height;
|
||||||
|
|
||||||
|
int device_rotation;
|
||||||
|
|
||||||
bool gain_is_manual;
|
bool gain_is_manual;
|
||||||
int gain;
|
int gain;
|
||||||
int gain_max;
|
int gain_max;
|
||||||
|
|
Loading…
Reference in New Issue