flash.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "flash.h"
  2. #include "gtk/gtk.h"
  3. #include <fcntl.h>
  4. #include <inttypes.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. typedef enum {
  8. FLASH_TYPE_LED,
  9. FLASH_TYPE_DISPLAY,
  10. } FlashType;
  11. typedef struct {
  12. char path[260];
  13. int fd;
  14. } MPLEDFlash;
  15. typedef struct {
  16. } MPDisplayFlash;
  17. struct _MPFlash {
  18. FlashType type;
  19. union {
  20. MPLEDFlash led;
  21. MPDisplayFlash display;
  22. };
  23. };
  24. MPFlash *
  25. mp_led_flash_from_path(const char *path)
  26. {
  27. MPFlash *flash = malloc(sizeof(MPFlash));
  28. flash->type = FLASH_TYPE_LED;
  29. strncpy(flash->led.path, path, 259);
  30. char mpath[275];
  31. snprintf(mpath, 275, "%s/flash_strobe", path);
  32. flash->led.fd = open(mpath, O_WRONLY);
  33. if (flash->led.fd == -1) {
  34. g_printerr("Failed to open %s\n", mpath);
  35. free(flash);
  36. return NULL;
  37. }
  38. return flash;
  39. }
  40. static GtkWidget *flash_window = NULL;
  41. static GDBusProxy *dbus_brightness_proxy = NULL;
  42. static int dbus_old_brightness = 0;
  43. static void
  44. dbus_brightness_init(GObject *src, GAsyncResult *res, gpointer *user_data)
  45. {
  46. g_autoptr(GError) err = NULL;
  47. dbus_brightness_proxy = g_dbus_proxy_new_finish(res, &err);
  48. if (!dbus_brightness_proxy || err) {
  49. printf("Failed to connect to dbus brightness service %s\n",
  50. err->message);
  51. return;
  52. }
  53. }
  54. void
  55. mp_flash_gtk_init(GDBusConnection *conn)
  56. {
  57. g_dbus_proxy_new(conn,
  58. G_DBUS_PROXY_FLAGS_NONE,
  59. NULL,
  60. "org.gnome.SettingsDaemon.Power",
  61. "/org/gnome/SettingsDaemon/Power",
  62. "org.gnome.SettingsDaemon.Power.Screen",
  63. NULL,
  64. (GAsyncReadyCallback)dbus_brightness_init,
  65. NULL);
  66. // Create a full screen full white window as a flash
  67. GtkWidget *window = gtk_window_new();
  68. // gtk_window_set_accept_focus(GTK_WINDOW(flash->display.window), FALSE);
  69. gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
  70. gtk_window_fullscreen(GTK_WINDOW(window));
  71. gtk_widget_add_css_class(window, "flash");
  72. flash_window = window;
  73. }
  74. void
  75. mp_flash_gtk_clean()
  76. {
  77. gtk_window_destroy(GTK_WINDOW(flash_window));
  78. g_object_unref(dbus_brightness_proxy);
  79. }
  80. MPFlash *
  81. mp_create_display_flash()
  82. {
  83. MPFlash *flash = malloc(sizeof(MPFlash));
  84. flash->type = FLASH_TYPE_DISPLAY;
  85. return flash;
  86. }
  87. void
  88. mp_flash_free(MPFlash *flash)
  89. {
  90. switch (flash->type) {
  91. case FLASH_TYPE_LED:
  92. close(flash->led.fd);
  93. break;
  94. case FLASH_TYPE_DISPLAY:
  95. break;
  96. }
  97. free(flash);
  98. }
  99. static void
  100. set_display_brightness(int brightness)
  101. {
  102. g_dbus_proxy_call(dbus_brightness_proxy,
  103. "org.freedesktop.DBus.Properties.Set",
  104. g_variant_new("(ssv)",
  105. "org.gnome.SettingsDaemon.Power.Screen",
  106. "Brightness",
  107. g_variant_new("i", brightness)),
  108. G_DBUS_CALL_FLAGS_NONE,
  109. -1,
  110. NULL,
  111. NULL,
  112. NULL);
  113. }
  114. static void
  115. brightness_received(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
  116. {
  117. g_autoptr(GError) error = NULL;
  118. g_autoptr(GVariant) result = g_dbus_proxy_call_finish(proxy, res, &error);
  119. if (!result) {
  120. printf("Failed to get display brightness: %s\n", error->message);
  121. return;
  122. }
  123. g_autoptr(GVariant) values = g_variant_get_child_value(result, 0);
  124. if (g_variant_n_children(values) == 0) {
  125. return;
  126. }
  127. g_autoptr(GVariant) brightness = g_variant_get_child_value(values, 0);
  128. dbus_old_brightness = g_variant_get_int32(brightness);
  129. }
  130. static bool
  131. show_display_flash(MPFlash *flash)
  132. {
  133. if (!flash_window)
  134. return false;
  135. gtk_widget_set_visible(flash_window, true);
  136. // First get brightness and then set brightness to 100%
  137. if (!dbus_brightness_proxy)
  138. return false;
  139. g_dbus_proxy_call(dbus_brightness_proxy,
  140. "org.freedesktop.DBus.Properties.Get",
  141. g_variant_new("(ss)",
  142. "org.gnome.SettingsDaemon.Power.Screen",
  143. "Brightness"),
  144. G_DBUS_CALL_FLAGS_NONE,
  145. -1,
  146. NULL,
  147. (GAsyncReadyCallback)brightness_received,
  148. NULL);
  149. set_display_brightness(100);
  150. return false;
  151. }
  152. void
  153. mp_flash_enable(MPFlash *flash)
  154. {
  155. switch (flash->type) {
  156. case FLASH_TYPE_LED:
  157. lseek(flash->led.fd, 0, SEEK_SET);
  158. dprintf(flash->led.fd, "1\n");
  159. break;
  160. case FLASH_TYPE_DISPLAY:
  161. g_main_context_invoke(NULL, (GSourceFunc)show_display_flash, flash);
  162. break;
  163. }
  164. }
  165. static bool
  166. hide_display_flash(MPFlash *flash)
  167. {
  168. if (!flash_window)
  169. return false;
  170. gtk_widget_set_visible(flash_window, false);
  171. set_display_brightness(dbus_old_brightness);
  172. return false;
  173. }
  174. void
  175. mp_flash_disable(MPFlash *flash)
  176. {
  177. switch (flash->type) {
  178. case FLASH_TYPE_LED:
  179. // Flash gets reset automatically
  180. break;
  181. case FLASH_TYPE_DISPLAY:
  182. g_main_context_invoke(NULL, (GSourceFunc)hide_display_flash, flash);
  183. break;
  184. }
  185. }