parent
8248b7ab47
commit
24835cdc25
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,3 +11,7 @@
|
|||
opacity: 0.9;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.flash {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 |
|
@ -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 |
|
@ -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>
|
||||
|
|
15
meson.build
15
meson.build
|
@ -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],
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -19,6 +19,7 @@ struct mp_io_pipeline_state {
|
|||
int exposure;
|
||||
|
||||
bool save_dng;
|
||||
bool flash_enabled;
|
||||
};
|
||||
|
||||
void mp_io_pipeline_start();
|
||||
|
|
15
src/main.c
15
src/main.c
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue