flash.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. GtkStyleContext *context;
  72. context = gtk_widget_get_style_context(window);
  73. gtk_style_context_add_class(context, "flash");
  74. flash_window = window;
  75. }
  76. void
  77. mp_flash_gtk_clean()
  78. {
  79. gtk_window_destroy(GTK_WINDOW(flash_window));
  80. g_object_unref(dbus_brightness_proxy);
  81. }
  82. MPFlash *
  83. mp_create_display_flash()
  84. {
  85. MPFlash *flash = malloc(sizeof(MPFlash));
  86. flash->type = FLASH_TYPE_DISPLAY;
  87. return flash;
  88. }
  89. void
  90. mp_flash_free(MPFlash *flash)
  91. {
  92. switch (flash->type) {
  93. case FLASH_TYPE_LED:
  94. close(flash->led.fd);
  95. break;
  96. case FLASH_TYPE_DISPLAY:
  97. break;
  98. }
  99. free(flash);
  100. }
  101. static void
  102. set_display_brightness(int brightness)
  103. {
  104. g_dbus_proxy_call(dbus_brightness_proxy,
  105. "org.freedesktop.DBus.Properties.Set",
  106. g_variant_new("(ssv)",
  107. "org.gnome.SettingsDaemon.Power.Screen",
  108. "Brightness",
  109. g_variant_new("i", brightness)),
  110. G_DBUS_CALL_FLAGS_NONE,
  111. -1,
  112. NULL,
  113. NULL,
  114. NULL);
  115. }
  116. static void
  117. brightness_received(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
  118. {
  119. g_autoptr(GError) error = NULL;
  120. g_autoptr(GVariant) result = g_dbus_proxy_call_finish(proxy, res, &error);
  121. if (!result) {
  122. printf("Failed to get display brightness: %s\n", error->message);
  123. return;
  124. }
  125. g_autoptr(GVariant) values = g_variant_get_child_value(result, 0);
  126. if (g_variant_n_children(values) == 0) {
  127. return;
  128. }
  129. g_autoptr(GVariant) brightness = g_variant_get_child_value(values, 0);
  130. dbus_old_brightness = g_variant_get_int32(brightness);
  131. }
  132. static bool
  133. show_display_flash(MPFlash *flash)
  134. {
  135. if (!flash_window)
  136. return false;
  137. gtk_widget_show(flash_window);
  138. // First get brightness and then set brightness to 100%
  139. if (!dbus_brightness_proxy)
  140. return false;
  141. g_dbus_proxy_call(dbus_brightness_proxy,
  142. "org.freedesktop.DBus.Properties.Get",
  143. g_variant_new("(ss)",
  144. "org.gnome.SettingsDaemon.Power.Screen",
  145. "Brightness"),
  146. G_DBUS_CALL_FLAGS_NONE,
  147. -1,
  148. NULL,
  149. (GAsyncReadyCallback)brightness_received,
  150. NULL);
  151. set_display_brightness(100);
  152. return false;
  153. }
  154. void
  155. mp_flash_enable(MPFlash *flash)
  156. {
  157. switch (flash->type) {
  158. case FLASH_TYPE_LED:
  159. lseek(flash->led.fd, 0, SEEK_SET);
  160. dprintf(flash->led.fd, "1\n");
  161. break;
  162. case FLASH_TYPE_DISPLAY:
  163. g_main_context_invoke(NULL, (GSourceFunc)show_display_flash, flash);
  164. break;
  165. }
  166. }
  167. static bool
  168. hide_display_flash(MPFlash *flash)
  169. {
  170. if (!flash_window)
  171. return false;
  172. gtk_widget_hide(flash_window);
  173. set_display_brightness(dbus_old_brightness);
  174. return false;
  175. }
  176. void
  177. mp_flash_disable(MPFlash *flash)
  178. {
  179. switch (flash->type) {
  180. case FLASH_TYPE_LED:
  181. // Flash gets reset automatically
  182. break;
  183. case FLASH_TYPE_DISPLAY:
  184. g_main_context_invoke(NULL, (GSourceFunc)hide_display_flash, flash);
  185. break;
  186. }
  187. }