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 tex_coord;
|
||||
|
||||
uniform mat3 transform;
|
||||
|
||||
varying vec2 uv;
|
||||
|
||||
void main() {
|
||||
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_height;
|
||||
|
||||
static int device_rotation;
|
||||
|
||||
struct control_state {
|
||||
bool gain_is_manual;
|
||||
int gain;
|
||||
|
@ -275,6 +277,7 @@ update_process_pipeline()
|
|||
.burst_length = burst_length,
|
||||
.preview_width = preview_width,
|
||||
.preview_height = preview_height,
|
||||
.device_rotation = device_rotation,
|
||||
.gain_is_manual = current_controls.gain_is_manual,
|
||||
.gain = current_controls.gain,
|
||||
.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 ||
|
||||
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;
|
||||
preview_width = state->preview_width;
|
||||
preview_height = state->preview_height;
|
||||
device_rotation = state->device_rotation;
|
||||
|
||||
if (camera) {
|
||||
struct control_state previous_desired = desired_controls;
|
||||
|
|
|
@ -10,6 +10,8 @@ struct mp_io_pipeline_state {
|
|||
int preview_width;
|
||||
int preview_height;
|
||||
|
||||
int device_rotation;
|
||||
|
||||
bool gain_is_manual;
|
||||
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_height = -1;
|
||||
|
||||
static int device_rotation = 0;
|
||||
|
||||
static bool gain_is_manual = false;
|
||||
static int gain;
|
||||
static int gain_max;
|
||||
|
@ -95,6 +97,7 @@ update_io_pipeline()
|
|||
.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,
|
||||
|
@ -215,6 +218,7 @@ mp_main_capture_completed(GdkTexture *thumb, const char *fname)
|
|||
}
|
||||
|
||||
static GLuint blit_program;
|
||||
static GLuint blit_uniform_transform;
|
||||
static GLuint blit_uniform_texture;
|
||||
static GLuint solid_program;
|
||||
static GLuint solid_uniform_color;
|
||||
|
@ -247,6 +251,7 @@ preview_realize(GtkGLArea *area)
|
|||
glBindAttribLocation(blit_program, GL_UTIL_TEX_COORD_ATTRIBUTE, "tex_coord");
|
||||
check_gl();
|
||||
|
||||
blit_uniform_transform = glGetUniformLocation(blit_program, "transform");
|
||||
blit_uniform_texture = glGetUniformLocation(blit_program, "texture");
|
||||
|
||||
GLuint solid_shaders[] = {
|
||||
|
@ -266,17 +271,26 @@ preview_realize(GtkGLArea *area)
|
|||
static void
|
||||
position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y)
|
||||
{
|
||||
int scale = gtk_widget_get_scale_factor(preview);
|
||||
int preview_height = gtk_widget_get_allocated_height(preview) * scale;
|
||||
int top_height = gtk_widget_get_allocated_height(preview_top_box) * scale;
|
||||
int bottom_height = gtk_widget_get_allocated_height(preview_bottom_box) * scale;
|
||||
int buffer_width, buffer_height;
|
||||
if (device_rotation == 0 || device_rotation == 180) {
|
||||
buffer_width = preview_buffer_width;
|
||||
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;
|
||||
|
||||
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 = preview_width;
|
||||
*size_y = preview_width * ratio;
|
||||
*size_x = scale * buffer_width;
|
||||
*size_y = scale * buffer_height;
|
||||
|
||||
*offset_x = (preview_width - *size_x) / 2.0;
|
||||
|
||||
if (*size_y > inner_height) {
|
||||
*offset_y = (preview_height - *size_y) / 2.0;
|
||||
|
@ -314,6 +328,19 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
|
|||
if (current_preview_buffer) {
|
||||
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);
|
||||
glBindTexture(GL_TEXTURE_2D, mp_process_pipeline_buffer_get_texture_id(current_preview_buffer));
|
||||
glUniform1i(blit_uniform_texture, 0);
|
||||
|
@ -719,6 +746,62 @@ create_simple_action(GtkApplication *app, const char *name, GCallback callback)
|
|||
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
|
||||
activate(GtkApplication *app, gpointer data)
|
||||
{
|
||||
|
@ -779,6 +862,21 @@ activate(GtkApplication *app, gpointer data)
|
|||
const char *quit_accels[] = { "<Ctrl>q", "<Ctrl>w", NULL };
|
||||
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();
|
||||
|
||||
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 const struct mp_camera_config *camera;
|
||||
static int camera_rotation;
|
||||
|
||||
static MPCameraMode mode;
|
||||
|
||||
|
@ -40,6 +41,8 @@ static int captures_remaining = 0;
|
|||
static int preview_width;
|
||||
static int preview_height;
|
||||
|
||||
static int device_rotation;
|
||||
|
||||
static int output_buffer_width = -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_MODEL, mp_get_device_model());
|
||||
uint16_t orientation;
|
||||
if (camera->rotate == 0) {
|
||||
if (camera_rotation == 0) {
|
||||
orientation = camera->mirrored ? ORIENTATION_TOPRIGHT :
|
||||
ORIENTATION_TOPLEFT;
|
||||
} else if (camera->rotate == 90) {
|
||||
} else if (camera_rotation == 90) {
|
||||
orientation = camera->mirrored ? ORIENTATION_RIGHTBOT :
|
||||
ORIENTATION_LEFTBOT;
|
||||
} else if (camera->rotate == 180) {
|
||||
} else if (camera_rotation == 180) {
|
||||
orientation = camera->mirrored ? ORIENTATION_BOTLEFT :
|
||||
ORIENTATION_BOTRIGHT;
|
||||
} else {
|
||||
|
@ -583,7 +586,7 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer)
|
|||
memcpy(image, buffer->data, size);
|
||||
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));
|
||||
|
||||
#ifdef PROFILE_PROCESS
|
||||
|
@ -692,10 +695,21 @@ on_output_changed()
|
|||
camera->blacklevel);
|
||||
}
|
||||
|
||||
static int
|
||||
mod(int a, int b)
|
||||
{
|
||||
int r = a % b;
|
||||
return r < 0 ? r + b : r;
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
mode = state->mode;
|
||||
|
@ -703,6 +717,8 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
|
|||
preview_width = state->preview_width;
|
||||
preview_height = state->preview_height;
|
||||
|
||||
device_rotation = state->device_rotation;
|
||||
|
||||
burst_length = state->burst_length;
|
||||
|
||||
// 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;
|
||||
|
||||
if (output_changed) {
|
||||
camera_rotation = mod(camera->rotate - device_rotation, 360);
|
||||
|
||||
on_output_changed();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ struct mp_process_pipeline_state {
|
|||
int preview_width;
|
||||
int preview_height;
|
||||
|
||||
int device_rotation;
|
||||
|
||||
bool gain_is_manual;
|
||||
int gain;
|
||||
int gain_max;
|
||||
|
|
Loading…
Reference in New Issue