Implement flash

Fixes #5
This commit is contained in:
Benjamin Schaaf 2021-01-04 23:39:17 +11:00
parent 8248b7ab47
commit 24835cdc25
16 changed files with 302 additions and 17 deletions

View File

@ -23,6 +23,7 @@ cropfactor=10.81
fnumber=3.0
iso-min=100
iso-max=64000
flash-path=/sys/class/leds/white:flash
[front]
driver=gc2145
@ -40,3 +41,4 @@ mirrored=true
focallength=2.6
cropfactor=12.7
fnumber=2.8
flash-display=true

View File

@ -23,6 +23,7 @@ cropfactor=10.81
fnumber=3.0
iso-min=100
iso-max=64000
flash-path=/sys/class/leds/white:flash
[front]
driver=gc2145
@ -40,3 +41,4 @@ mirrored=true
focallength=2.6
cropfactor=12.7
fnumber=2.8
flash-display=true

View File

@ -24,6 +24,7 @@ cropfactor=10.81
fnumber=3.0
iso-min=100
iso-max=64000
flash-path=/sys/class/leds/white:flash
[front]
driver=gc2145
@ -41,3 +42,4 @@ mirrored=true
focallength=2.6
cropfactor=12.7
fnumber=2.8
flash-display=true

View File

@ -11,3 +11,7 @@
opacity: 0.9;
background-color: rgba(0, 0, 0, 0.2);
}
.flash {
background-color: #ffffff;
}

View File

@ -59,6 +59,15 @@
</style>
</object>
</child>
<child>
<object class="GtkButton" id="flash-controls-button">
<property name="valign">start</property>
<property name="icon-name">flash-enabled-symbolic</property>
<style>
<class name="circular"/>
</style>
</object>
</child>
</object>
</child>
<child>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
height="32"
width="32"
viewBox="0 0 8.4666665 8.466667">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<path
style="fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 3 0 L 1.5 1.5 L 30.5 30.5 L 32 29 L 20.75 17.75 L 24 13 L 16 13 L 15.234375 12.234375 L 19 0 L 13 0 L 10.726562 7.7265625 L 3 0 z M 9.3632812 12.363281 L 8 17 L 14 17 L 9.3632812 12.363281 z M 14.789062 17.789062 L 11 32 L 18.3125 21.3125 L 14.789062 17.789062 z "
transform="scale(0.26458334)"
id="path1370" />
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
height="32"
width="32"
viewBox="0 0 8.4666665 8.466667">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<path
style="fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:0.26458335px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 3.4395834,0 2.1166667,4.4979167 H 3.96875 L 2.9104167,8.4666669 6.3500001,3.4395834 H 3.96875 L 5.0270834,0 Z"
id="path1370" />
</svg>

After

Width:  |  Height:  |  Size: 992 B

View File

@ -4,11 +4,13 @@
<file preprocess="xml-stripblanks">camera.ui</file>
<file preprocess="xml-stripblanks">controls-popover.ui</file>
<file>camera.css</file>
<file preprocess="xml-stripblanks">switch-camera-symbolic.svg</file>
<file preprocess="xml-stripblanks">shutter-button-symbolic.svg</file>
<file preprocess="xml-stripblanks">flash-disabled-symbolic.svg</file>
<file preprocess="xml-stripblanks">flash-enabled-symbolic.svg</file>
<file preprocess="xml-stripblanks">folder-symbolic.svg</file>
<file preprocess="xml-stripblanks">settings-symbolic.svg</file>
<file preprocess="xml-stripblanks">shutter-button-symbolic.svg</file>
<file preprocess="xml-stripblanks">shutter-symbolic.svg</file>
<file preprocess="xml-stripblanks">switch-camera-symbolic.svg</file>
<file>blit.vert</file>
<file>blit.frag</file>
<file>solid.vert</file>

View File

@ -34,18 +34,19 @@ if get_option('tiffcfapattern')
endif
executable('megapixels',
'src/main.c',
'src/ini.c',
'src/gles2_debayer.c',
'src/gl_util.c',
'src/camera.c',
'src/device.c',
'src/pipeline.c',
'src/camera_config.c',
'src/device.c',
'src/flash.c',
'src/gl_util.c',
'src/gles2_debayer.c',
'src/ini.c',
'src/io_pipeline.c',
'src/main.c',
'src/matrix.c',
'src/pipeline.c',
'src/process_pipeline.c',
'src/zbar_pipeline.c',
'src/matrix.c',
resources,
include_directories: 'src/',
dependencies: [gtkdep, libm, tiff, zbar, threads, epoxy],

View File

@ -206,6 +206,10 @@ config_ini_handler(void *user, const char *section, const char *name,
cc->iso_min = strtod(value, NULL);
} else if (strcmp(name, "iso-max") == 0) {
cc->iso_max = strtod(value, NULL);
} else if (strcmp(name, "flash-path") == 0) {
strcpy(cc->flash_path, value);
} else if (strcmp(name, "flash-display") == 0) {
cc->flash_display = strcmp(value, "true") == 0;
} else {
g_printerr("Unknown key '%s' in [%s]\n", name, section);
exit(1);

View File

@ -41,6 +41,9 @@ struct mp_camera_config {
double fnumber;
int iso_min;
int iso_max;
char flash_path[260];
bool flash_display;
};
bool mp_load_config();

141
src/flash.c Normal file
View File

@ -0,0 +1,141 @@
#include "flash.h"
#include "gtk/gtk.h"
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <inttypes.h>
typedef enum {
FLASH_TYPE_LED,
FLASH_TYPE_DISPLAY,
} FlashType;
typedef struct {
char path[260];
int fd;
} MPLEDFlash;
typedef struct {
GtkWidget *window;
} MPDisplayFlash;
struct _MPFlash {
FlashType type;
union {
MPLEDFlash led;
MPDisplayFlash display;
};
};
MPFlash *
mp_led_flash_from_path(const char * path)
{
MPFlash *flash = malloc(sizeof(MPFlash));
flash->type = FLASH_TYPE_LED;
strncpy(flash->led.path, path, 259);
char mpath[275];
snprintf(mpath, 275, "%s/flash_strobe", path);
flash->led.fd = open(mpath, O_WRONLY);
if (flash->led.fd == -1) {
g_printerr("Failed to open %s\n", mpath);
free(flash);
return NULL;
}
return flash;
}
static bool create_display(MPFlash *flash)
{
// Create a full screen full white window as a flash
GtkWidget *window = gtk_window_new();
// gtk_window_set_accept_focus(GTK_WINDOW(flash->display.window), FALSE);
gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
gtk_window_fullscreen(GTK_WINDOW(window));
GtkStyleContext *context;
context = gtk_widget_get_style_context(window);
gtk_style_context_add_class(context, "flash");
flash->display.window = window;
return false;
}
MPFlash *
mp_create_display_flash()
{
MPFlash *flash = malloc(sizeof(MPFlash));
flash->type = FLASH_TYPE_DISPLAY;
flash->display.window = NULL;
// All GTK functions must be called on the main thread
g_main_context_invoke(NULL, (GSourceFunc)create_display, flash);
return flash;
}
static bool flash_free(MPFlash *flash)
{
gtk_window_destroy(GTK_WINDOW(flash->display.window));
free(flash);
return false;
}
void
mp_flash_free(MPFlash *flash)
{
switch (flash->type) {
case FLASH_TYPE_LED:
close(flash->led.fd);
free(flash);
break;
case FLASH_TYPE_DISPLAY:
g_main_context_invoke(NULL, (GSourceFunc)flash_free, flash);
break;
}
}
static bool show_flash_window(MPFlash *flash)
{
gtk_widget_show(flash->display.window);
return false;
}
void
mp_flash_enable(MPFlash *flash)
{
switch (flash->type) {
case FLASH_TYPE_LED:
lseek(flash->led.fd, 0, SEEK_SET);
dprintf(flash->led.fd, "1\n");
break;
case FLASH_TYPE_DISPLAY:
g_main_context_invoke(NULL, (GSourceFunc)show_flash_window, flash);
break;
}
}
static bool hide_flash_window(MPFlash *flash)
{
gtk_widget_hide(flash->display.window);
return false;
}
void
mp_flash_disable(MPFlash *flash)
{
switch (flash->type) {
case FLASH_TYPE_LED:
// Flash gets reset automatically
break;
case FLASH_TYPE_DISPLAY:
g_main_context_invoke(NULL, (GSourceFunc)hide_flash_window, flash);
break;
}
}

8
src/flash.h Normal file
View File

@ -0,0 +1,8 @@
typedef struct _MPFlash MPFlash;
MPFlash *mp_led_flash_from_path(const char *path);
MPFlash *mp_create_display_flash();
void mp_flash_free(MPFlash *flash);
void mp_flash_enable(MPFlash *flash);
void mp_flash_disable(MPFlash *flash);

View File

@ -1,16 +1,17 @@
#include "io_pipeline.h"
#include "device.h"
#include "camera.h"
#include "device.h"
#include "flash.h"
#include "pipeline.h"
#include "process_pipeline.h"
#include <string.h>
#include <glib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
struct media_link_info {
unsigned int source_entity_id;
@ -29,6 +30,8 @@ struct camera_info {
MPCamera *camera;
MPFlash *flash;
int gain_ctrl;
int gain_max;
@ -90,6 +93,8 @@ struct control_state {
static struct control_state desired_controls = {};
static struct control_state current_controls = {};
static bool flash_enabled = false;
static bool want_focus = false;
static MPPipeline *pipeline;
@ -216,6 +221,15 @@ setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config)
info->gain_ctrl = V4L2_CID_ANALOGUE_GAIN;
info->gain_max = control.max;
}
// Setup flash
if (config->flash_path[0]) {
info->flash = mp_led_flash_from_path(config->flash_path);
} else if (config->flash_display) {
info->flash = mp_create_display_flash();
} else {
info->flash = NULL;
}
}
}
@ -340,6 +354,11 @@ capture(MPPipeline *pipeline, const void *data)
mp_camera_start_capture(info->camera);
// Enable flash
if (info->flash && flash_enabled) {
mp_flash_enable(info->flash);
}
update_process_pipeline();
mp_process_pipeline_capture();
@ -490,6 +509,11 @@ on_frame(MPBuffer buffer, void * _data)
mp_camera_start_capture(info->camera);
// Disable flash
if (info->flash) {
mp_flash_disable(info->flash);
}
update_process_pipeline();
}
}
@ -571,8 +595,12 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
desired_controls.exposure = state->exposure;
has_changed =
has_changed || memcmp(&previous_desired, &desired_controls,
sizeof(struct control_state)) != 0;
has_changed
|| memcmp(&previous_desired, &desired_controls,
sizeof(struct control_state)) != 0
|| flash_enabled != state->flash_enabled;
flash_enabled = state->flash_enabled;
}
assert(has_changed);

View File

@ -19,6 +19,7 @@ struct mp_io_pipeline_state {
int exposure;
bool save_dng;
bool flash_enabled;
};
void mp_io_pipeline_start();

View File

@ -52,6 +52,8 @@ static int exposure;
static bool has_auto_focus_continuous;
static bool has_auto_focus_start;
static bool flash_enabled = true;
static bool setting_save_dng;
static MPProcessPipelineBuffer *current_preview_buffer = NULL;
@ -107,6 +109,7 @@ update_io_pipeline()
.exposure_is_manual = exposure_is_manual,
.exposure = exposure,
.save_dng = setting_save_dng,
.flash_enabled = flash_enabled,
};
mp_io_pipeline_update_state(&io_state);
}
@ -758,6 +761,16 @@ open_shutter_controls(GtkWidget *button, gpointer user_data)
open_controls(button, "Shutter", 1.0, 360.0, exposure, !exposure_is_manual, set_shutter, set_shutter_auto);
}
static void
flash_button_clicked(GtkWidget *button, gpointer user_data)
{
flash_enabled = !flash_enabled;
update_io_pipeline();
const char * icon_name = flash_enabled ? "flash-enabled-symbolic" : "flash-disabled-symbolic";
gtk_button_set_icon_name(GTK_BUTTON(button), icon_name);
}
static void
on_realize(GtkWidget *window, gpointer *data)
{
@ -895,6 +908,7 @@ activate(GtkApplication *app, gpointer data)
GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
GtkWidget *iso_button = GTK_WIDGET(gtk_builder_get_object(builder, "iso-controls-button"));
GtkWidget *shutter_button = GTK_WIDGET(gtk_builder_get_object(builder, "shutter-controls-button"));
GtkWidget *flash_button = GTK_WIDGET(gtk_builder_get_object(builder, "flash-controls-button"));
GtkWidget *setting_dng_button = GTK_WIDGET(gtk_builder_get_object(builder, "setting-raw"));
preview = GTK_WIDGET(gtk_builder_get_object(builder, "preview"));
main_stack = GTK_WIDGET(gtk_builder_get_object(builder, "main_stack"));
@ -916,6 +930,7 @@ activate(GtkApplication *app, gpointer data)
g_signal_connect(iso_button, "clicked", G_CALLBACK(open_iso_controls), NULL);
g_signal_connect(shutter_button, "clicked", G_CALLBACK(open_shutter_controls), NULL);
g_signal_connect(flash_button, "clicked", G_CALLBACK(flash_button_clicked), NULL);
// Setup actions
create_simple_action(app, "capture", G_CALLBACK(run_capture_action));