Compare commits
10 Commits
b4b0a61230
...
5f2b7136ca
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5f2b7136ca | ||
![]() |
886fea58bd | ||
![]() |
4c29f88069 | ||
![]() |
928714595d | ||
![]() |
529e7841ab | ||
![]() |
f64782d9a5 | ||
![]() |
9567f00e01 | ||
![]() |
22549185f8 | ||
![]() |
17228b1afa | ||
![]() |
4db24ddc5e |
@@ -33,6 +33,7 @@ MAIN_PICTURE="$BURST_DIR"/1
|
|||||||
if [ -f "$MAIN_PICTURE.jpg" ]; then
|
if [ -f "$MAIN_PICTURE.jpg" ]; then
|
||||||
# Just move over the main jpeg if this was a YUV capture
|
# Just move over the main jpeg if this was a YUV capture
|
||||||
cp "$MAIN_PICTURE.jpg" "$TARGET_NAME.jpg"
|
cp "$MAIN_PICTURE.jpg" "$TARGET_NAME.jpg"
|
||||||
|
echo "$TARGET_NAME.jpg"
|
||||||
|
|
||||||
# Clean up the temp dir containing the burst
|
# Clean up the temp dir containing the burst
|
||||||
rm -rf "$BURST_DIR"
|
rm -rf "$BURST_DIR"
|
||||||
|
@@ -27,6 +27,9 @@ finish-args:
|
|||||||
# camera shutter feedback
|
# camera shutter feedback
|
||||||
- --talk-name=org.sigxcpu.Feedback
|
- --talk-name=org.sigxcpu.Feedback
|
||||||
|
|
||||||
|
# accelerometer sensor for orientation
|
||||||
|
- --system-talk-name=net.hadess.SensorProxy
|
||||||
|
|
||||||
modules:
|
modules:
|
||||||
- name: megapixels
|
- name: megapixels
|
||||||
buildsystem: meson
|
buildsystem: meson
|
||||||
|
@@ -54,6 +54,7 @@ executable('megapixels',
|
|||||||
'src/matrix.c',
|
'src/matrix.c',
|
||||||
'src/pipeline.c',
|
'src/pipeline.c',
|
||||||
'src/process_pipeline.c',
|
'src/process_pipeline.c',
|
||||||
|
'src/rotation.c',
|
||||||
'src/zbar_pipeline.c',
|
'src/zbar_pipeline.c',
|
||||||
'src/dcp.c',
|
'src/dcp.c',
|
||||||
resources,
|
resources,
|
||||||
@@ -126,6 +127,8 @@ if clang_format.found()
|
|||||||
'src/pipeline.h',
|
'src/pipeline.h',
|
||||||
'src/process_pipeline.c',
|
'src/process_pipeline.c',
|
||||||
'src/process_pipeline.h',
|
'src/process_pipeline.h',
|
||||||
|
'src/rotation.c',
|
||||||
|
'src/rotation.h',
|
||||||
'src/zbar_pipeline.c',
|
'src/zbar_pipeline.c',
|
||||||
'src/zbar_pipeline.h',
|
'src/zbar_pipeline.h',
|
||||||
'tools/camera_test.c',
|
'tools/camera_test.c',
|
||||||
|
@@ -96,6 +96,8 @@ update_process_pipeline()
|
|||||||
.preview_width = state_io.preview_width,
|
.preview_width = state_io.preview_width,
|
||||||
.preview_height = state_io.preview_height,
|
.preview_height = state_io.preview_height,
|
||||||
.device_rotation = state_io.device_rotation,
|
.device_rotation = state_io.device_rotation,
|
||||||
|
.device_accel_rotation = state_io.device_accel_rotation,
|
||||||
|
.device_accel_rotation_good = state_io.device_accel_rotation_good,
|
||||||
|
|
||||||
.gain.control = state_io.gain.control,
|
.gain.control = state_io.gain.control,
|
||||||
.gain.auto_control = state_io.gain.auto_control,
|
.gain.auto_control = state_io.gain.auto_control,
|
||||||
@@ -669,6 +671,8 @@ update_state(MPPipeline *pipeline, const mp_state_io *new_state)
|
|||||||
state_io.preview_width = new_state->preview_width;
|
state_io.preview_width = new_state->preview_width;
|
||||||
state_io.preview_height = new_state->preview_height;
|
state_io.preview_height = new_state->preview_height;
|
||||||
state_io.device_rotation = new_state->device_rotation;
|
state_io.device_rotation = new_state->device_rotation;
|
||||||
|
state_io.device_accel_rotation = new_state->device_accel_rotation;
|
||||||
|
state_io.device_accel_rotation_good = new_state->device_accel_rotation_good;
|
||||||
|
|
||||||
if (state_io.camera) {
|
if (state_io.camera) {
|
||||||
state_io.gain.value = new_state->gain.value;
|
state_io.gain.value = new_state->gain.value;
|
||||||
|
41
src/main.c
41
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 "rotation.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include <asm/errno.h>
|
#include <asm/errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -120,6 +121,8 @@ update_io_pipeline()
|
|||||||
.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,
|
.device_rotation = state.device_rotation,
|
||||||
|
.device_accel_rotation = state.device_accel_rotation,
|
||||||
|
.device_accel_rotation_good = state.device_accel_rotation_good,
|
||||||
|
|
||||||
.gain.control = state.gain.control,
|
.gain.control = state.gain.control,
|
||||||
.gain.auto_control = state.gain.auto_control,
|
.gain.auto_control = state.gain.auto_control,
|
||||||
@@ -315,7 +318,7 @@ struct capture_completed_args {
|
|||||||
static bool
|
static bool
|
||||||
capture_completed(struct capture_completed_args *args)
|
capture_completed(struct capture_completed_args *args)
|
||||||
{
|
{
|
||||||
strncpy(last_path, args->fname, 259);
|
snprintf(last_path, sizeof(last_path), args->fname);
|
||||||
|
|
||||||
gtk_image_set_from_paintable(GTK_IMAGE(thumb_last),
|
gtk_image_set_from_paintable(GTK_IMAGE(thumb_last),
|
||||||
GDK_PAINTABLE(args->thumb));
|
GDK_PAINTABLE(args->thumb));
|
||||||
@@ -615,7 +618,7 @@ run_open_last_action(GSimpleAction *action, GVariant *param, gpointer user_data)
|
|||||||
if (strlen(last_path) == 0) {
|
if (strlen(last_path) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sprintf(uri, "file://%s", last_path);
|
snprintf(uri, sizeof(uri), "file://%s", last_path);
|
||||||
if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) {
|
if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) {
|
||||||
g_printerr("Could not launch image viewer for '%s': %s\n",
|
g_printerr("Could not launch image viewer for '%s': %s\n",
|
||||||
uri,
|
uri,
|
||||||
@@ -628,7 +631,7 @@ run_open_photos_action(GSimpleAction *action, GVariant *param, gpointer user_dat
|
|||||||
{
|
{
|
||||||
char uri[270];
|
char uri[270];
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
sprintf(uri, "file://%s", g_get_user_special_dir(G_USER_DIRECTORY_PICTURES));
|
snprintf(uri, sizeof(uri), "file://%s", g_get_user_special_dir(G_USER_DIRECTORY_PICTURES));
|
||||||
if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) {
|
if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) {
|
||||||
g_printerr("Could not launch image viewer: %s\n", error->message);
|
g_printerr("Could not launch image viewer: %s\n", error->message);
|
||||||
}
|
}
|
||||||
@@ -1291,6 +1294,17 @@ xevent_handler(GdkDisplay *display, XEvent *xevent, gpointer data)
|
|||||||
}
|
}
|
||||||
#endif // GDK_WINDOWING_X11
|
#endif // GDK_WINDOWING_X11
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotation_sensor_handler(int rotation, bool good)
|
||||||
|
{
|
||||||
|
if (rotation != state.device_accel_rotation ||
|
||||||
|
good != state.device_accel_rotation_good) {
|
||||||
|
state.device_accel_rotation = rotation;
|
||||||
|
state.device_accel_rotation_good = good;
|
||||||
|
update_io_pipeline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
activate(GtkApplication *app, gpointer data)
|
activate(GtkApplication *app, gpointer data)
|
||||||
{
|
{
|
||||||
@@ -1381,7 +1395,12 @@ activate(GtkApplication *app, gpointer data)
|
|||||||
create_simple_action(app, "quit", G_CALLBACK(run_quit_action));
|
create_simple_action(app, "quit", G_CALLBACK(run_quit_action));
|
||||||
|
|
||||||
// Setup shortcuts
|
// Setup shortcuts
|
||||||
const char *capture_accels[] = { "space", NULL };
|
const char *capture_accels[] = {
|
||||||
|
"space",
|
||||||
|
"AudioLowerVolume",
|
||||||
|
"AudioRaiseVolume",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
gtk_application_set_accels_for_action(app, "app.capture", capture_accels);
|
gtk_application_set_accels_for_action(app, "app.capture", capture_accels);
|
||||||
|
|
||||||
const char *quit_accels[] = { "<Ctrl>q", "<Ctrl>w", NULL };
|
const char *quit_accels[] = { "<Ctrl>q", "<Ctrl>w", NULL };
|
||||||
@@ -1394,15 +1413,17 @@ activate(GtkApplication *app, gpointer data)
|
|||||||
// Initialize the postprocessing gsetting to the old processor if
|
// Initialize the postprocessing gsetting to the old processor if
|
||||||
// it was not set yet
|
// it was not set yet
|
||||||
if (setting_postproc == NULL || setting_postproc[0] == '\0') {
|
if (setting_postproc == NULL || setting_postproc[0] == '\0') {
|
||||||
|
const int size = 512;
|
||||||
printf("Initializing postprocessor gsetting\n");
|
printf("Initializing postprocessor gsetting\n");
|
||||||
setting_postproc = malloc(512);
|
setting_postproc = malloc(size);
|
||||||
if (!mp_process_find_processor(setting_postproc, "postprocess.sh")) {
|
if (!mp_process_find_processor(setting_postproc, size, "postprocess.sh")) {
|
||||||
printf("No processor found\n");
|
printf("No processor found\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
g_settings_set_string(settings, "postprocessor", setting_postproc);
|
g_settings_set_string(settings, "postprocessor", setting_postproc);
|
||||||
printf("Initialized postprocessor to %s\n", setting_postproc);
|
printf("Initialized postprocessor to %s\n", setting_postproc);
|
||||||
}
|
}
|
||||||
|
free(setting_postproc);
|
||||||
|
|
||||||
// Find all postprocessors for the settings list
|
// Find all postprocessors for the settings list
|
||||||
mp_process_find_all_processors(setting_postprocessor_list);
|
mp_process_find_all_processors(setting_postprocessor_list);
|
||||||
@@ -1472,6 +1493,7 @@ activate(GtkApplication *app, gpointer data)
|
|||||||
GDBusConnection *conn =
|
GDBusConnection *conn =
|
||||||
g_application_get_dbus_connection(G_APPLICATION(app));
|
g_application_get_dbus_connection(G_APPLICATION(app));
|
||||||
mp_flash_gtk_init(conn);
|
mp_flash_gtk_init(conn);
|
||||||
|
mp_device_rotation_init(rotation_sensor_handler);
|
||||||
|
|
||||||
if (state.configuration->count > 0) {
|
if (state.configuration->count > 0) {
|
||||||
mp_io_pipeline_start();
|
mp_io_pipeline_start();
|
||||||
@@ -1481,6 +1503,12 @@ activate(GtkApplication *app, gpointer data)
|
|||||||
|
|
||||||
gtk_application_add_window(app, GTK_WINDOW(window));
|
gtk_application_add_window(app, GTK_WINDOW(window));
|
||||||
gtk_widget_set_visible(window, true);
|
gtk_widget_set_visible(window, true);
|
||||||
|
|
||||||
|
// Inhibit system shortcuts to be able to use
|
||||||
|
// VolumeUp and VolumeDown hardware buttons to take a picture
|
||||||
|
GtkNative *native = gtk_widget_get_native (GTK_WIDGET (window));
|
||||||
|
GdkSurface *surface = gtk_native_get_surface (native);
|
||||||
|
gdk_toplevel_inhibit_system_shortcuts (GDK_TOPLEVEL (surface), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1501,6 +1529,7 @@ shutdown(GApplication *app, gpointer data)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
mp_io_pipeline_stop();
|
mp_io_pipeline_stop();
|
||||||
mp_flash_gtk_clean();
|
mp_flash_gtk_clean();
|
||||||
|
mp_device_rotation_clean();
|
||||||
|
|
||||||
g_clear_object(&fb_settings);
|
g_clear_object(&fb_settings);
|
||||||
g_clear_object(&capture_event);
|
g_clear_object(&capture_event);
|
||||||
|
@@ -68,7 +68,7 @@ mp_process_find_all_processors(GtkListStore *store)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for a script in XDG_CONFIG_HOME
|
// Check for a script in XDG_CONFIG_HOME
|
||||||
sprintf(buffer, "%s/megapixels/postprocess.sh", g_get_user_config_dir());
|
snprintf(buffer, sizeof(buffer), "%s/megapixels/postprocess.sh", g_get_user_config_dir());
|
||||||
if (access(buffer, F_OK) != -1) {
|
if (access(buffer, F_OK) != -1) {
|
||||||
gtk_list_store_insert(store, &iter, -1);
|
gtk_list_store_insert(store, &iter, -1);
|
||||||
gtk_list_store_set(
|
gtk_list_store_set(
|
||||||
@@ -76,7 +76,7 @@ mp_process_find_all_processors(GtkListStore *store)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check user overridden /etc/megapixels/postprocess.sh
|
// Check user overridden /etc/megapixels/postprocess.sh
|
||||||
sprintf(buffer, "%s/megapixels/postprocess.sh", SYSCONFDIR);
|
snprintf(buffer, sizeof(buffer), "%s/megapixels/postprocess.sh", SYSCONFDIR);
|
||||||
if (access(buffer, F_OK) != -1) {
|
if (access(buffer, F_OK) != -1) {
|
||||||
gtk_list_store_insert(store, &iter, -1);
|
gtk_list_store_insert(store, &iter, -1);
|
||||||
gtk_list_store_set(
|
gtk_list_store_set(
|
||||||
@@ -84,7 +84,7 @@ mp_process_find_all_processors(GtkListStore *store)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check user overridden /usr/share/megapixels/postprocess.sh
|
// Check user overridden /usr/share/megapixels/postprocess.sh
|
||||||
sprintf(buffer, "%s/megapixels/postprocess.sh", DATADIR);
|
snprintf(buffer, sizeof(buffer), "%s/megapixels/postprocess.sh", DATADIR);
|
||||||
if (access(buffer, F_OK) != -1) {
|
if (access(buffer, F_OK) != -1) {
|
||||||
gtk_list_store_insert(store, &iter, -1);
|
gtk_list_store_insert(store, &iter, -1);
|
||||||
gtk_list_store_set(
|
gtk_list_store_set(
|
||||||
@@ -94,7 +94,7 @@ mp_process_find_all_processors(GtkListStore *store)
|
|||||||
// Find extra packaged postprocessor scripts
|
// Find extra packaged postprocessor scripts
|
||||||
// These should be packaged in
|
// These should be packaged in
|
||||||
// /usr/share/megapixels/postprocessor.d/executable
|
// /usr/share/megapixels/postprocessor.d/executable
|
||||||
sprintf(buffer, "%s/megapixels/postprocessor.d", DATADIR);
|
snprintf(buffer, sizeof(buffer), "%s/megapixels/postprocessor.d", DATADIR);
|
||||||
DIR *d;
|
DIR *d;
|
||||||
struct dirent *dir;
|
struct dirent *dir;
|
||||||
d = opendir(buffer);
|
d = opendir(buffer);
|
||||||
@@ -103,10 +103,11 @@ mp_process_find_all_processors(GtkListStore *store)
|
|||||||
if (dir->d_name[0] == '.') {
|
if (dir->d_name[0] == '.') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sprintf(buffer,
|
snprintf(buffer,
|
||||||
"%s/megapixels/postprocessor.d/%s",
|
sizeof(buffer),
|
||||||
DATADIR,
|
"%s/megapixels/postprocessor.d/%s",
|
||||||
dir->d_name);
|
DATADIR,
|
||||||
|
dir->d_name);
|
||||||
gtk_list_store_insert(store, &iter, -1);
|
gtk_list_store_insert(store, &iter, -1);
|
||||||
gtk_list_store_set(
|
gtk_list_store_set(
|
||||||
store, &iter, 0, buffer, 1, dir->d_name, -1);
|
store, &iter, 0, buffer, 1, dir->d_name, -1);
|
||||||
@@ -116,32 +117,32 @@ mp_process_find_all_processors(GtkListStore *store)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
mp_process_find_processor(char *script, char *filename)
|
mp_process_find_processor(char *script, int size, char *filename)
|
||||||
{
|
{
|
||||||
// Check postprocess.sh in the current working directory
|
// Check postprocess.sh in the current working directory
|
||||||
sprintf(script, "./data/%s", filename);
|
snprintf(script, size, "./data/%s", filename);
|
||||||
if (access(script, F_OK) != -1) {
|
if (access(script, F_OK) != -1) {
|
||||||
sprintf(script, "./data/%s", filename);
|
snprintf(script, size, "./data/%s", filename);
|
||||||
printf("Found postprocessor script at %s\n", script);
|
printf("Found postprocessor script at %s\n", script);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a script in XDG_CONFIG_HOME
|
// Check for a script in XDG_CONFIG_HOME
|
||||||
sprintf(script, "%s/megapixels/%s", g_get_user_config_dir(), filename);
|
snprintf(script, size, "%s/megapixels/%s", g_get_user_config_dir(), filename);
|
||||||
if (access(script, F_OK) != -1) {
|
if (access(script, F_OK) != -1) {
|
||||||
printf("Found postprocessor script at %s\n", script);
|
printf("Found postprocessor script at %s\n", script);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check user overridden /etc/megapixels/postprocessor.sh
|
// Check user overridden /etc/megapixels/postprocessor.sh
|
||||||
sprintf(script, "%s/megapixels/%s", SYSCONFDIR, filename);
|
snprintf(script, size, "%s/megapixels/%s", SYSCONFDIR, filename);
|
||||||
if (access(script, F_OK) != -1) {
|
if (access(script, F_OK) != -1) {
|
||||||
printf("Found postprocessor script at %s\n", script);
|
printf("Found postprocessor script at %s\n", script);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check packaged /usr/share/megapixels/postprocessor.sh
|
// Check packaged /usr/share/megapixels/postprocessor.sh
|
||||||
sprintf(script, "%s/megapixels/%s", DATADIR, filename);
|
snprintf(script, size, "%s/megapixels/%s", DATADIR, filename);
|
||||||
if (access(script, F_OK) != -1) {
|
if (access(script, F_OK) != -1) {
|
||||||
printf("Found postprocessor script at %s\n", script);
|
printf("Found postprocessor script at %s\n", script);
|
||||||
return true;
|
return true;
|
||||||
@@ -161,7 +162,7 @@ static void setup_capture(void)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(burst_dir, tempdir);
|
snprintf(burst_dir, sizeof(burst_dir), tempdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -175,7 +176,7 @@ setup(MPPipeline *pipeline, const void *data)
|
|||||||
state_proc.mode_exposure = AAA_BY_V4L2_CONTROLS;
|
state_proc.mode_exposure = AAA_BY_V4L2_CONTROLS;
|
||||||
state_proc.mode_focus = AAA_DISABLED;
|
state_proc.mode_focus = AAA_DISABLED;
|
||||||
|
|
||||||
if (!mp_process_find_processor(movie_script, "movie.sh")) {
|
if (!mp_process_find_processor(movie_script, sizeof(movie_script), "movie.sh")) {
|
||||||
fprintf(stderr,"movie.sh not found, video pipeline disabled\n");
|
fprintf(stderr,"movie.sh not found, video pipeline disabled\n");
|
||||||
}
|
}
|
||||||
setup_capture();
|
setup_capture();
|
||||||
@@ -525,10 +526,11 @@ summarize()
|
|||||||
(float) time, (float) gain, state_proc.gain.value, state_proc.dgain.value,
|
(float) time, (float) gain, state_proc.gain.value, state_proc.dgain.value,
|
||||||
(float) 1/diopt);
|
(float) 1/diopt);
|
||||||
|
|
||||||
sprintf(buf, "1/%s%.0f%sISO%s%.0f%sm%s%.2f",
|
snprintf(buf, sizeof(buf),
|
||||||
sep, (float) (1.0/time), sep,
|
"1/%s%.0f%sISO%s%.0f%sm%s%.2f",
|
||||||
sep, (float) (gain*100),
|
sep, (float) (1.0/time), sep,
|
||||||
sep, sep, 1/diopt);
|
sep, (float) (gain*100),
|
||||||
|
sep, sep, 1/diopt);
|
||||||
|
|
||||||
/* Not sure what to do here. Looks like we need to call gtk
|
/* Not sure what to do here. Looks like we need to call gtk
|
||||||
functions from main thread.
|
functions from main thread.
|
||||||
@@ -979,9 +981,10 @@ save_grw(const uint8_t *image, char *fname)
|
|||||||
fwrite(image, size, 1, outfile);
|
fwrite(image, size, 1, outfile);
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
int header = sprintf(buf+1,
|
int header = snprintf(buf + 1,
|
||||||
"Caps: video/x-raw,format=%s,width=%d,height=%d\nSize: %d\nGRW",
|
sizeof(buf) - 1,
|
||||||
format, width, height, size);
|
"Caps: video/x-raw,format=%s,width=%d,height=%d\nSize: %d\nGRW",
|
||||||
|
format, width, height, size);
|
||||||
fwrite(buf, header+1, 1, outfile);
|
fwrite(buf, header+1, 1, outfile);
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
}
|
}
|
||||||
@@ -1067,13 +1070,14 @@ save_jpeg(const uint8_t *image, char *fname)
|
|||||||
jpeg_finish_compress(&cinfo);
|
jpeg_finish_compress(&cinfo);
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
jpeg_destroy_compress(&cinfo);
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
free(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_image_for_capture_yuv(const uint8_t *image, int count)
|
process_image_for_capture_yuv(const uint8_t *image, int count)
|
||||||
{
|
{
|
||||||
char fname[255];
|
char fname[255];
|
||||||
sprintf(fname, "%s/%d.jpg", burst_dir, count);
|
snprintf(fname, sizeof(fname), "%s/%d.jpg", burst_dir, count);
|
||||||
|
|
||||||
save_jpeg(image, fname);
|
save_jpeg(image, fname);
|
||||||
}
|
}
|
||||||
@@ -1233,7 +1237,7 @@ static void
|
|||||||
process_image_for_capture_bayer(const uint8_t *image, int count)
|
process_image_for_capture_bayer(const uint8_t *image, int count)
|
||||||
{
|
{
|
||||||
char fname[255];
|
char fname[255];
|
||||||
sprintf(fname, "%s/%d.dng", burst_dir, count);
|
snprintf(fname, sizeof(fname), "%s/%d.dng", burst_dir, count);
|
||||||
|
|
||||||
save_dng(image, fname, count);
|
save_dng(image, fname, count);
|
||||||
}
|
}
|
||||||
@@ -1258,21 +1262,27 @@ static void
|
|||||||
post_process_finished(GSubprocess *proc, GAsyncResult *res, GdkTexture *thumb)
|
post_process_finished(GSubprocess *proc, GAsyncResult *res, GdkTexture *thumb)
|
||||||
{
|
{
|
||||||
char *stdout;
|
char *stdout;
|
||||||
|
char *path;
|
||||||
g_subprocess_communicate_utf8_finish(proc, res, &stdout, NULL, NULL);
|
g_subprocess_communicate_utf8_finish(proc, res, &stdout, NULL, NULL);
|
||||||
|
|
||||||
// The last line contains the file name
|
// The last line contains the file name
|
||||||
int end = strlen(stdout);
|
int end = strlen(stdout);
|
||||||
// Skip the newline at the end
|
|
||||||
stdout[--end] = '\0';
|
|
||||||
|
|
||||||
char *path = path = stdout + end - 1;
|
if (end > 0) {
|
||||||
do {
|
// Skip the newline at the end
|
||||||
if (*path == '\n') {
|
stdout[--end] = '\0';
|
||||||
path++;
|
|
||||||
break;
|
path = stdout + end - 1;
|
||||||
}
|
do {
|
||||||
--path;
|
if (*path == '\n') {
|
||||||
} while (path > stdout);
|
path++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--path;
|
||||||
|
} while (path > stdout);
|
||||||
|
} else {
|
||||||
|
path = stdout;
|
||||||
|
}
|
||||||
|
|
||||||
mp_main_capture_completed(thumb, path);
|
mp_main_capture_completed(thumb, path);
|
||||||
}
|
}
|
||||||
@@ -1286,20 +1296,23 @@ process_capture_burst(GdkTexture *thumb)
|
|||||||
format_timestamp(timestamp);
|
format_timestamp(timestamp);
|
||||||
|
|
||||||
if (g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) != NULL) {
|
if (g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) != NULL) {
|
||||||
sprintf(capture_fname,
|
snprintf(capture_fname,
|
||||||
"%s/IMG%s",
|
sizeof(capture_fname),
|
||||||
g_get_user_special_dir(G_USER_DIRECTORY_PICTURES),
|
"%s/IMG%s",
|
||||||
timestamp);
|
g_get_user_special_dir(G_USER_DIRECTORY_PICTURES),
|
||||||
|
timestamp);
|
||||||
} else if (getenv("XDG_PICTURES_DIR") != NULL) {
|
} else if (getenv("XDG_PICTURES_DIR") != NULL) {
|
||||||
sprintf(capture_fname,
|
snprintf(capture_fname,
|
||||||
"%s/IMG%s",
|
sizeof(capture_fname),
|
||||||
getenv("XDG_PICTURES_DIR"),
|
"%s/IMG%s",
|
||||||
timestamp);
|
getenv("XDG_PICTURES_DIR"),
|
||||||
|
timestamp);
|
||||||
} else {
|
} else {
|
||||||
sprintf(capture_fname,
|
snprintf(capture_fname,
|
||||||
"%s/Pictures/IMG%s",
|
sizeof(capture_fname),
|
||||||
getenv("HOME"),
|
"%s/Pictures/IMG%s",
|
||||||
timestamp);
|
getenv("HOME"),
|
||||||
|
timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool save_dng = g_settings_get_boolean(settings, "save-raw");
|
bool save_dng = g_settings_get_boolean(settings, "save-raw");
|
||||||
@@ -1564,7 +1577,9 @@ update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
|
|||||||
new_state->camera->current_mode) ||
|
new_state->camera->current_mode) ||
|
||||||
state_proc.preview_width != new_state->preview_width ||
|
state_proc.preview_width != new_state->preview_width ||
|
||||||
state_proc.preview_height != new_state->preview_height ||
|
state_proc.preview_height != new_state->preview_height ||
|
||||||
state_proc.device_rotation != new_state->device_rotation;
|
state_proc.device_rotation != new_state->device_rotation ||
|
||||||
|
state_proc.device_accel_rotation != new_state->device_accel_rotation ||
|
||||||
|
state_proc.device_accel_rotation_good != new_state->device_accel_rotation_good;
|
||||||
|
|
||||||
bool format_changed = state_proc.mode == NULL;
|
bool format_changed = state_proc.mode == NULL;
|
||||||
|
|
||||||
@@ -1579,6 +1594,8 @@ update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
|
|||||||
state_proc.preview_height = new_state->preview_height;
|
state_proc.preview_height = new_state->preview_height;
|
||||||
|
|
||||||
state_proc.device_rotation = new_state->device_rotation;
|
state_proc.device_rotation = new_state->device_rotation;
|
||||||
|
state_proc.device_accel_rotation = new_state->device_accel_rotation;
|
||||||
|
state_proc.device_accel_rotation_good = new_state->device_accel_rotation_good;
|
||||||
state_proc.burst_length = new_state->burst_length;
|
state_proc.burst_length = new_state->burst_length;
|
||||||
|
|
||||||
state_proc.balance[0] = new_state->balance[0];
|
state_proc.balance[0] = new_state->balance[0];
|
||||||
@@ -1602,9 +1619,12 @@ update_state(MPPipeline *pipeline, const mp_state_proc *new_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (output_changed || camera_changed) {
|
if (output_changed || camera_changed) {
|
||||||
|
int rotation;
|
||||||
|
rotation = state_proc.device_accel_rotation_good ?
|
||||||
|
state_proc.device_accel_rotation :
|
||||||
|
state_proc.device_rotation;
|
||||||
state_proc.camera_rotation = mod(
|
state_proc.camera_rotation = mod(
|
||||||
state_proc.mode->rotation - state_proc.device_rotation, 360);
|
state_proc.mode->rotation - rotation, 360);
|
||||||
|
|
||||||
on_output_changed(format_changed);
|
on_output_changed(format_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,7 +37,8 @@ struct mp_process_pipeline_state {
|
|||||||
bool control_focus;
|
bool control_focus;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool mp_process_find_processor(char *script, char *filename);
|
|
||||||
|
bool mp_process_find_processor(char *script, int size, char *filename);
|
||||||
void mp_process_find_all_processors(GtkListStore *store);
|
void mp_process_find_all_processors(GtkListStore *store);
|
||||||
|
|
||||||
void mp_process_pipeline_start();
|
void mp_process_pipeline_start();
|
||||||
|
182
src/rotation.c
Normal file
182
src/rotation.c
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
#include "gtk/gtk.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "rotation.h"
|
||||||
|
|
||||||
|
struct sensor_cb_data {
|
||||||
|
sensor_cb rotation_update;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GDBusProxy *iio_proxy;
|
||||||
|
static bool rotation_valid = false;
|
||||||
|
static int rotation;
|
||||||
|
struct sensor_cb_data cb_data;
|
||||||
|
|
||||||
|
static int
|
||||||
|
rotation_string_to_degree(const gchar* val)
|
||||||
|
{
|
||||||
|
int rot = -1;
|
||||||
|
if (!g_ascii_strcasecmp(val, "normal"))
|
||||||
|
rot = 0;
|
||||||
|
if (!g_ascii_strcasecmp(val, "right-up"))
|
||||||
|
rot = 270;
|
||||||
|
if (!g_ascii_strcasecmp(val, "left-up"))
|
||||||
|
rot = 90;
|
||||||
|
if (!g_ascii_strcasecmp(val, "bottom-up"))
|
||||||
|
rot = 180;
|
||||||
|
return rot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotation_properties_changed (GDBusProxy *proxy,
|
||||||
|
GVariant *changed_properties,
|
||||||
|
GStrv invalidated_properties,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GVariant *v;
|
||||||
|
GVariantDict dict;
|
||||||
|
const gchar *val;
|
||||||
|
struct sensor_cb_data *cb_data = (struct sensor_cb_data*)user_data;
|
||||||
|
|
||||||
|
g_variant_dict_init (&dict, changed_properties);
|
||||||
|
|
||||||
|
if (g_variant_dict_contains (&dict, "HasAccelerometer")) {
|
||||||
|
v = g_dbus_proxy_get_cached_property (iio_proxy, "HasAccelerometer");
|
||||||
|
rotation_valid = g_variant_get_boolean (v);
|
||||||
|
g_debug ("accelerometer changed: %d\n", rotation_valid);
|
||||||
|
g_variant_unref (v);
|
||||||
|
}
|
||||||
|
if (g_variant_dict_contains (&dict, "AccelerometerOrientation")) {
|
||||||
|
v = g_dbus_proxy_get_cached_property (iio_proxy, "AccelerometerOrientation");
|
||||||
|
val = g_variant_get_string (v, NULL);
|
||||||
|
rotation = rotation_string_to_degree(val);
|
||||||
|
g_variant_unref (v);
|
||||||
|
}
|
||||||
|
g_variant_dict_clear (&dict);
|
||||||
|
|
||||||
|
g_debug ("sensor rotation changed: %d %d\n",
|
||||||
|
rotation, rotation_valid);
|
||||||
|
cb_data->rotation_update(rotation, rotation_valid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotation_get_initial_values (struct sensor_cb_data *cb_data)
|
||||||
|
{
|
||||||
|
GVariant *v;
|
||||||
|
const gchar *val;
|
||||||
|
|
||||||
|
v = g_dbus_proxy_get_cached_property (iio_proxy, "HasAccelerometer");
|
||||||
|
rotation_valid = g_variant_get_boolean (v);
|
||||||
|
if (rotation_valid) {
|
||||||
|
g_variant_unref (v);
|
||||||
|
v = g_dbus_proxy_get_cached_property (iio_proxy, "AccelerometerOrientation");
|
||||||
|
val = g_variant_get_string (v, NULL);
|
||||||
|
rotation = rotation_string_to_degree(val);
|
||||||
|
g_debug ("rotation: %d\n", rotation);
|
||||||
|
} else
|
||||||
|
g_debug ("no accelerometer\n");
|
||||||
|
g_variant_unref (v);
|
||||||
|
cb_data->rotation_update(rotation, rotation_valid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotation_accelerometer_claimed(GDBusProxy *proxy,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
struct sensor_cb_data *cb_data = (struct sensor_cb_data*)user_data;
|
||||||
|
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(GVariant) result = g_dbus_proxy_call_finish(proxy, res, &error);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
g_warning ("Failed to claim accelerometer: %s",
|
||||||
|
error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rotation_get_initial_values (cb_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotation_iio_proxy_init (GObject *src,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
struct sensor_cb_data *cb_data = (struct sensor_cb_data*)user_data;
|
||||||
|
g_autoptr(GError) err = NULL;
|
||||||
|
|
||||||
|
iio_proxy = g_dbus_proxy_new_finish(res, &err);
|
||||||
|
if (!iio_proxy || err) {
|
||||||
|
g_warning ("Failed to connect to sensor proxy service %s\n",
|
||||||
|
err->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (G_OBJECT (iio_proxy), "g-properties-changed",
|
||||||
|
G_CALLBACK (rotation_properties_changed),
|
||||||
|
cb_data);
|
||||||
|
|
||||||
|
g_dbus_proxy_call (iio_proxy,
|
||||||
|
"ClaimAccelerometer",
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
NULL,
|
||||||
|
(GAsyncReadyCallback)rotation_accelerometer_claimed,
|
||||||
|
cb_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotation_iio_proxy_appeared_cb (GDBusConnection *connection,
|
||||||
|
const gchar *name,
|
||||||
|
const gchar *name_owner,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_debug ("iio-sensor-proxy appeared\n");
|
||||||
|
g_dbus_proxy_new (connection,
|
||||||
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
|
NULL,
|
||||||
|
"net.hadess.SensorProxy",
|
||||||
|
"/net/hadess/SensorProxy",
|
||||||
|
"net.hadess.SensorProxy",
|
||||||
|
NULL,
|
||||||
|
(GAsyncReadyCallback)rotation_iio_proxy_init,
|
||||||
|
user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rotation_iio_proxy_vanished_cb (GDBusConnection *connection,
|
||||||
|
const gchar *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
struct sensor_cb_data *cb_data = (struct sensor_cb_data*)user_data;
|
||||||
|
|
||||||
|
if (iio_proxy) {
|
||||||
|
g_clear_object (&iio_proxy);
|
||||||
|
g_debug ("iio-sensor-proxy vanished\n");
|
||||||
|
|
||||||
|
rotation_valid = false;
|
||||||
|
rotation = 0;
|
||||||
|
cb_data->rotation_update(rotation, rotation_valid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mp_device_rotation_init(sensor_cb cb)
|
||||||
|
{
|
||||||
|
g_assert(cb != NULL);
|
||||||
|
cb_data.rotation_update = cb;
|
||||||
|
g_bus_watch_name (G_BUS_TYPE_SYSTEM,
|
||||||
|
"net.hadess.SensorProxy",
|
||||||
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||||
|
rotation_iio_proxy_appeared_cb,
|
||||||
|
rotation_iio_proxy_vanished_cb,
|
||||||
|
&cb_data,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mp_device_rotation_clean(void)
|
||||||
|
{
|
||||||
|
g_object_unref(iio_proxy);
|
||||||
|
}
|
9
src/rotation.h
Normal file
9
src/rotation.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _MP_ROTATION_H
|
||||||
|
#define _MP_ROTATION_H
|
||||||
|
|
||||||
|
typedef void(*sensor_cb)(int, bool);
|
||||||
|
|
||||||
|
void mp_device_rotation_init(sensor_cb cb);
|
||||||
|
void mp_device_rotation_clean(void);
|
||||||
|
|
||||||
|
#endif
|
@@ -29,6 +29,8 @@ typedef struct state_main {
|
|||||||
int preview_buffer_height;
|
int preview_buffer_height;
|
||||||
|
|
||||||
int device_rotation;
|
int device_rotation;
|
||||||
|
int device_accel_rotation;
|
||||||
|
bool device_accel_rotation_good;
|
||||||
|
|
||||||
int burst_length;
|
int burst_length;
|
||||||
|
|
||||||
@@ -70,6 +72,8 @@ typedef struct state_io {
|
|||||||
int preview_width;
|
int preview_width;
|
||||||
int preview_height;
|
int preview_height;
|
||||||
int device_rotation;
|
int device_rotation;
|
||||||
|
int device_accel_rotation;
|
||||||
|
bool device_accel_rotation_good;
|
||||||
} mp_state_io;
|
} mp_state_io;
|
||||||
|
|
||||||
typedef enum aaa_mode {
|
typedef enum aaa_mode {
|
||||||
@@ -93,6 +97,8 @@ typedef struct state_proc {
|
|||||||
|
|
||||||
// Device orientation in degrees
|
// Device orientation in degrees
|
||||||
int device_rotation;
|
int device_rotation;
|
||||||
|
int device_accel_rotation;
|
||||||
|
bool device_accel_rotation_good;
|
||||||
// Camera orientation as number
|
// Camera orientation as number
|
||||||
int camera_rotation;
|
int camera_rotation;
|
||||||
|
|
||||||
|
@@ -241,6 +241,8 @@ process_image(MPPipeline *pipeline, MPZBarImage **_image)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Preview pixel format not supported - zbar won't work\n");
|
printf("Preview pixel format not supported - zbar won't work\n");
|
||||||
|
free(data);
|
||||||
|
mp_zbar_image_unref(image);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user