diff --git a/src/flash.c b/src/flash.c index 930bcd8..69b8a4c 100644 --- a/src/flash.c +++ b/src/flash.c @@ -17,7 +17,6 @@ typedef struct { } MPLEDFlash; typedef struct { - GtkWidget *window; } MPDisplayFlash; struct _MPFlash { @@ -49,8 +48,33 @@ mp_led_flash_from_path(const char * path) return flash; } -static bool create_display(MPFlash *flash) +static GtkWidget *flash_window = NULL; +static GDBusProxy *dbus_brightness_proxy = NULL; +static int dbus_old_brightness = 0; + +static void dbus_brightness_init(GObject *src, GAsyncResult *res, gpointer *user_data) { + GError *err = NULL; + dbus_brightness_proxy = g_dbus_proxy_new_finish (res, &err); + if (!dbus_brightness_proxy || err) { + printf("Failed to connect to dbus brightness service %s\n", err->message); + g_object_unref(err); + return; + } +} + +void mp_flash_gtk_init(GDBusConnection *conn) +{ + g_dbus_proxy_new(conn, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.gnome.SettingsDaemon.Power", + "/org/gnome/SettingsDaemon/Power", + "org.gnome.SettingsDaemon.Power.Screen", + NULL, + (GAsyncReadyCallback)dbus_brightness_init, + NULL); + // 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); @@ -61,9 +85,13 @@ static bool create_display(MPFlash *flash) context = gtk_widget_get_style_context(window); gtk_style_context_add_class(context, "flash"); - flash->display.window = window; + flash_window = window; +} - return false; +void mp_flash_gtk_clean() +{ + gtk_window_destroy(GTK_WINDOW(flash_window)); + g_object_unref(dbus_brightness_proxy); } MPFlash * @@ -71,38 +99,87 @@ 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; } + + free(flash); } -static bool show_flash_window(MPFlash *flash) +static void set_display_brightness(int brightness) { - gtk_widget_show(flash->display.window); + g_dbus_proxy_call(dbus_brightness_proxy, + "org.freedesktop.DBus.Properties.Set", + g_variant_new( + "(ssv)", + "org.gnome.SettingsDaemon.Power.Screen", + "Brightness", + g_variant_new("i", brightness)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); +} + +static void brightness_received(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + GVariant *result = g_dbus_proxy_call_finish(proxy, res, &error); + + if (!result) { + printf("Failed to get display brightness: %s\n", error->message); + g_object_unref(error); + return; + } + + GVariant *values = g_variant_get_child_value(result, 0); + if (g_variant_n_children(values) == 0) { + return; + } + + GVariant *brightness = g_variant_get_child_value(values, 0); + dbus_old_brightness = g_variant_get_int32(brightness); + + g_variant_unref(result); +} + +static bool show_display_flash(MPFlash *flash) +{ + if (!flash_window) + return false; + + gtk_widget_show(flash_window); + + // First get brightness and then set brightness to 100% + if (!dbus_brightness_proxy) + return false; + + g_dbus_proxy_call(dbus_brightness_proxy, + "org.freedesktop.DBus.Properties.Get", + g_variant_new( + "(ss)", + "org.gnome.SettingsDaemon.Power.Screen", + "Brightness"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback)brightness_received, + NULL); + + set_display_brightness(100); + return false; } @@ -115,14 +192,19 @@ mp_flash_enable(MPFlash *flash) dprintf(flash->led.fd, "1\n"); break; case FLASH_TYPE_DISPLAY: - g_main_context_invoke(NULL, (GSourceFunc)show_flash_window, flash); + g_main_context_invoke(NULL, (GSourceFunc)show_display_flash, flash); break; } } -static bool hide_flash_window(MPFlash *flash) +static bool hide_display_flash(MPFlash *flash) { - gtk_widget_hide(flash->display.window); + if (!flash_window) + return false; + + gtk_widget_hide(flash_window); + set_display_brightness(dbus_old_brightness); + return false; } @@ -134,7 +216,7 @@ mp_flash_disable(MPFlash *flash) // Flash gets reset automatically break; case FLASH_TYPE_DISPLAY: - g_main_context_invoke(NULL, (GSourceFunc)hide_flash_window, flash); + g_main_context_invoke(NULL, (GSourceFunc)hide_display_flash, flash); break; } } diff --git a/src/flash.h b/src/flash.h index 9ff8813..de77e27 100644 --- a/src/flash.h +++ b/src/flash.h @@ -1,5 +1,10 @@ +#include "gio/gio.h" + typedef struct _MPFlash MPFlash; +void mp_flash_gtk_init(GDBusConnection *conn); +void mp_flash_gtk_clean(); + MPFlash *mp_led_flash_from_path(const char *path); MPFlash *mp_create_display_flash(); void mp_flash_free(MPFlash *flash); diff --git a/src/main.c b/src/main.c index cf653a2..6fa4a59 100644 --- a/src/main.c +++ b/src/main.c @@ -1,27 +1,28 @@ #include "main.h" +#include "camera_config.h" +#include "flash.h" +#include "gl_util.h" +#include "io_pipeline.h" +#include "process_pipeline.h" +#include +#include #include #include -#include +#include +#include +#include #include #include +#include +#include #include #include #include -#include -#include -#include -#include #include -#include +#include #include -#include -#include #include -#include "gl_util.h" -#include "camera_config.h" -#include "io_pipeline.h" -#include "process_pipeline.h" #define RENDERDOC @@ -970,6 +971,9 @@ activate(GtkApplication *app, gpointer data) NULL); update_screen_rotation(conn); + // Initialize display flash + mp_flash_gtk_init(conn); + mp_io_pipeline_start(); gtk_application_add_window(app, GTK_WINDOW(window)); @@ -982,6 +986,7 @@ shutdown(GApplication *app, gpointer data) // Only do cleanup in development, let the OS clean up otherwise #ifdef DEBUG mp_io_pipeline_stop(); + mp_flash_gtk_clean(); #endif }