From 033ce81baf0a920f3620e0d3c368c2b42a7fa979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A5=D0=B8=D1=80=D0=B5=D1=86=D0=BA=D0=B8=D0=B9=20=D0=9C?= =?UTF-8?q?=D0=B8=D1=85=D0=B0=D0=B8=D0=BB?= Date: Tue, 12 Feb 2019 15:55:46 +0300 Subject: [PATCH] =?UTF-8?q?sys-boot/plymouth-calculate-plugin:=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BF=D0=BB=D0=B0?= =?UTF-8?q?=D0=B3=D0=B8=D0=BD=20=D0=B4=D0=BB=D1=8F=20=D1=82=D0=B5=D0=BC?= =?UTF-8?q?=D1=8B=20plymouth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sys-boot/plymouth-calculate-plugin/Manifest | 1 + .../files/0.9.3-glibc-sysmacros.patch | 45 + .../files/calculate.plymouth | 15 + .../plymouth-calculate-plugin/files/plugin.c | 1208 +++++++++++++++++ .../plymouth-calculate-plugin-0.9.4.ebuild | 113 ++ 5 files changed, 1382 insertions(+) create mode 100644 sys-boot/plymouth-calculate-plugin/Manifest create mode 100644 sys-boot/plymouth-calculate-plugin/files/0.9.3-glibc-sysmacros.patch create mode 100644 sys-boot/plymouth-calculate-plugin/files/calculate.plymouth create mode 100644 sys-boot/plymouth-calculate-plugin/files/plugin.c create mode 100644 sys-boot/plymouth-calculate-plugin/plymouth-calculate-plugin-0.9.4.ebuild diff --git a/sys-boot/plymouth-calculate-plugin/Manifest b/sys-boot/plymouth-calculate-plugin/Manifest new file mode 100644 index 000000000..8c959d026 --- /dev/null +++ b/sys-boot/plymouth-calculate-plugin/Manifest @@ -0,0 +1 @@ +DIST plymouth-0.9.4.tar.xz 1103496 BLAKE2B abad2cefb89e9d17b77113396d7203090544759b3dd7f73f67153d9f126db28e5366d36aa11e2335566bf4046bebd50d8d9dd47c75634446fb3a0314cd458925 SHA512 83eb2de7e6d0980e9f7fa4e0b0f20c46a8238051d84bc38dbbb5dfa438e41c1a39846dcd652374256d9f1fe79967b154a3576cd9c433ef816b6c962be2d31e93 diff --git a/sys-boot/plymouth-calculate-plugin/files/0.9.3-glibc-sysmacros.patch b/sys-boot/plymouth-calculate-plugin/files/0.9.3-glibc-sysmacros.patch new file mode 100644 index 000000000..8969161bb --- /dev/null +++ b/sys-boot/plymouth-calculate-plugin/files/0.9.3-glibc-sysmacros.patch @@ -0,0 +1,45 @@ +From f8d7813b32dfe129d1e5718719ee3eff131f4fac Mon Sep 17 00:00:00 2001 +From: Kjell Claesson +Date: Fri, 18 Aug 2017 00:25:56 +0200 +Subject: [PATCH] Fix build with newer glibc + +Signed-off-by: Gilles Dartiguelongue +--- + configure.ac | 1 + + src/libply-splash-core/ply-terminal.c | 8 ++++++++ + 2 files changed, 9 insertions(+) + +diff --git a/configure.ac b/configure.ac +index c32697f..8376789 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -5,6 +5,7 @@ AC_CONFIG_AUX_DIR(build-tools) + + AC_USE_SYSTEM_EXTENSIONS + AC_SYS_LARGEFILE ++AC_HEADER_MAJOR + AC_PROG_AWK + AC_PROG_CC_STDC + AM_PROG_CC_C_O +diff --git a/src/libply-splash-core/ply-terminal.c b/src/libply-splash-core/ply-terminal.c +index a0954f2..ef62bf8 100644 +--- a/src/libply-splash-core/ply-terminal.c ++++ b/src/libply-splash-core/ply-terminal.c +@@ -36,6 +36,14 @@ + #include + #include + ++/* major()/minor() */ ++#ifdef MAJOR_IN_MKDEV ++# include ++#endif ++#ifdef MAJOR_IN_SYSMACROS ++# include ++#endif ++ + #include + #include + #include +-- +2.14.1 + diff --git a/sys-boot/plymouth-calculate-plugin/files/calculate.plymouth b/sys-boot/plymouth-calculate-plugin/files/calculate.plymouth new file mode 100644 index 000000000..efcdeb268 --- /dev/null +++ b/sys-boot/plymouth-calculate-plugin/files/calculate.plymouth @@ -0,0 +1,15 @@ +[Plymouth Theme] +Name=Calculate +Description=Simple theme that shows progressbar, image and text +ModuleName=calculate + +[calculate] +ImageDir=/usr/share/plymouth/themes/calculate +BackgroundStartColor=0x000000 +BackgroundEndColor=0x000000 +ProgressbarColor=0xcdc481 +BootImage=/usr/share/plymouth/themes/calculate/boot +ShutdownImage=/usr/share/plymouth/themes/calculate/shutdown +ShutdownText=Shutdown... +ShutdownFont=DroidSand 30 +ShutdownTextColor=0xaaaaaa diff --git a/sys-boot/plymouth-calculate-plugin/files/plugin.c b/sys-boot/plymouth-calculate-plugin/files/plugin.c new file mode 100644 index 000000000..77dfc1930 --- /dev/null +++ b/sys-boot/plymouth-calculate-plugin/files/plugin.c @@ -0,0 +1,1208 @@ +/* calculate.c - boot splash plugin + * + * Copyright (C) 2007, 2008 Red Hat, Inc. + * Copyright (C) 2019, Mir Calculate Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: Ray Strode + * Will Woods + * Modified by: Mir Calculate + */ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ply-boot-splash-plugin.h" +#include "ply-buffer.h" +#include "ply-entry.h" +#include "ply-event-loop.h" +#include "ply-key-file.h" +#include "ply-label.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-image.h" +#include "ply-trigger.h" +#include "ply-pixel-buffer.h" +#include "ply-pixel-display.h" +#include "ply-utils.h" + +#include "ply-throbber.h" +#include "ply-array.h" +#include + +struct _ply_progress_bar +{ + ply_pixel_display_t *display; + ply_rectangle_t area; + + double percent_done; + + uint32_t is_hidden : 1; +}; + +#include "ply-progress-bar.h" + + +void +ply_progress_bar_draw_area_color (ply_progress_bar_t *progress_bar, + ply_pixel_buffer_t *buffer, + long x, + long y, + unsigned long width, + unsigned long height, + uint32_t progressbar_color) +{ + ply_rectangle_t paint_area; + + if (progress_bar->is_hidden) + return; + + paint_area.x = x; + paint_area.y = y; + paint_area.width = width; + paint_area.height = height; + + ply_rectangle_intersect (&progress_bar->area, &paint_area, &paint_area); + ply_pixel_buffer_fill_with_hex_color (buffer, + &paint_area, + progressbar_color); +} + +struct _ply_throbber +{ + ply_array_t *frames; + ply_event_loop_t *loop; + char *image_dir; + char *frames_prefix; + + ply_pixel_display_t *display; + ply_rectangle_t frame_area; + ply_trigger_t *stop_trigger; + + long x, y; + long width, height; + double start_time, now; + + int frame_number; + uint32_t is_stopped : 1; +}; + +#ifndef FRAMES_PER_SECOND +#define FRAMES_PER_SECOND 30 +#endif + +#define BAR_HEIGHT 3 + +typedef enum +{ + PLY_BOOT_SPLASH_DISPLAY_NORMAL, + PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY, + PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY +} ply_boot_splash_display_type_t; + +typedef struct +{ + ply_boot_splash_plugin_t *plugin; + ply_pixel_display_t *display; + ply_entry_t *entry; + ply_throbber_t *throbber; + ply_progress_bar_t *progress_bar; + ply_label_t *label; + ply_label_t *message_label; + ply_label_t *shutdown_label; + ply_rectangle_t box_area, lock_area, logo_area, bar_area; +} view_t; + +struct _ply_boot_splash_plugin +{ + ply_event_loop_t *loop; + ply_boot_splash_mode_t mode; + ply_image_t *logo_image; + ply_image_t *lock_image; + ply_image_t *box_image; + ply_list_t *views; + + char *image_dir; + char *shutdown_font; + char *shutdown_text; + char *boot_image; + char *shutdown_image; + ply_boot_splash_display_type_t state; + + uint32_t background_start_color; + uint32_t background_end_color; + uint32_t progressbar_color; + uint32_t shutdown_color; + + ply_trigger_t *idle_trigger; + + uint32_t root_is_mounted : 1; + uint32_t is_visible : 1; + uint32_t is_animating : 1; + uint32_t is_idle : 1; +}; + +bool is_dir(const char* path) { + struct stat path_stat; + stat(path, &path_stat); + return S_ISDIR(path_stat.st_mode); +} + +void image_get_res(const char *basedir, int *xres, int *yres) +{ + FILE *fp; + char buf[512]; + int oxres, oyres; + + oxres = *xres; + oyres = *yres; + snprintf(buf, 512, "%s/%dx%d.png", basedir, oxres, oyres); + + fp = fopen(buf, "r"); + if (!fp) { + *xres = 1024; + *yres = 768; + unsigned int t, tx, ty, mdist = 0xffffffff; + struct dirent *dent; + DIR *tdir; + + snprintf(buf, 512, "%s", basedir); + tdir = opendir(buf); + if (!tdir) { + *xres = 0; + *yres = 0; + return; + } + while ((dent = readdir(tdir))) { + if (sscanf(dent->d_name, "%dx%d.png", &tx, &ty) != 2) + continue; + + /* We only want configs for resolutions smaller than the current one, + * so that we can actually fit the image on the screen. */ + if (tx >= oxres || ty >= oyres) + continue; + + t = (tx - oxres) * (tx - oxres) + (ty - oyres) * (ty - oyres); + + /* Penalize configs for resolutions with different aspect ratios. */ + if (oxres / oyres != tx / ty) + t *= 10; + + if (t < mdist) { + *xres = tx; + *yres = ty; + mdist = t; + } + } + closedir(tdir); + } else { + fclose(fp); + } +} + +char *detect_image(const char *logo_image, int xres, int yres) { + char *buf; + if(logo_image != NULL) { + if(is_dir(logo_image)) { + image_get_res(logo_image, &xres, &yres); + if(asprintf(&buf, "%s/%dx%d.png", logo_image, xres, yres) != -1) + return buf; + } else { + return strdup (logo_image); + } + } + return NULL; +} + +ply_boot_splash_plugin_interface_t *ply_boot_splash_plugin_get_interface (void); +static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin); + +static void become_idle (ply_boot_splash_plugin_t *plugin, + ply_trigger_t *idle_trigger); + +static view_t * +view_new (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + view_t *view; + + view = calloc (1, sizeof(view_t)); + view->plugin = plugin; + view->display = display; + + view->entry = ply_entry_new (plugin->image_dir); + view->throbber = ply_throbber_new (plugin->image_dir, + "throbber-"); + view->progress_bar = ply_progress_bar_new (); + view->label = ply_label_new (); + view->message_label = ply_label_new (); + view->shutdown_label = ply_label_new (); + + return view; +} + +static void +view_free (view_t *view) +{ + ply_entry_free (view->entry); + ply_throbber_free (view->throbber); + ply_progress_bar_free (view->progress_bar); + ply_label_free (view->label); + ply_label_free (view->message_label); + ply_label_free (view->shutdown_label); + + free (view); +} + +static void +free_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_free (view); + ply_list_remove_node (plugin->views, node); + + node = next_node; + } + + ply_list_free (plugin->views); + plugin->views = NULL; +} + +static bool +view_load (view_t *view) +{ + ply_trace ("loading entry"); + if (!ply_entry_load (view->entry)) + return false; + + ply_trace ("loading throbber"); + if (!ply_throbber_load (view->throbber)) + return true; + + return true; +} + +static bool +load_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + bool view_loaded; + + view_loaded = false; + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view_load (view)) + view_loaded = true; + + node = next_node; + } + + return view_loaded; +} + +static void +view_redraw (view_t *view) +{ + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); +} + +static void +redraw_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_redraw (view); + + node = next_node; + } +} + +static void +pause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + ply_trace ("pausing views"); + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_pause_updates (view->display); + + node = next_node; + } +} + +static void +unpause_views (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + ply_trace ("unpausing views"); + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_pixel_display_unpause_updates (view->display); + + node = next_node; + } +} + +static void +view_start_animation (view_t *view) +{ + ply_boot_splash_plugin_t *plugin; + + unsigned long screen_width, screen_height; + long width, height; + long x,y; + int number_of_frames; + + assert (view != NULL); + + plugin = view->plugin; + + assert (plugin != NULL); + assert (plugin->loop != NULL); + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + ply_pixel_display_draw_area (view->display, 0, 0, + screen_width, screen_height); + + if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN && + plugin->shutdown_font != NULL && plugin->shutdown_text != NULL) { + ply_label_set_text (view->shutdown_label, plugin->shutdown_text); + ply_label_set_font (view->shutdown_label, plugin->shutdown_font); + ply_label_set_color(view->shutdown_label, + ((plugin->shutdown_color >> 16) & 0xff) / 255.0f, + ((plugin->shutdown_color >> 8) & 0xff) / 255.0f, + (plugin->shutdown_color & 0xff) / 255.0f, + 1.0f); + int label_width = screen_width; + ply_label_set_width (view->shutdown_label, label_width); + ply_label_set_alignment (view->shutdown_label, PLY_LABEL_ALIGN_CENTER); + + x = 0; + y = screen_height / 2; + ply_label_show (view->shutdown_label, view->display, x, y); + } + + plugin->is_idle = false; + + number_of_frames = ply_array_get_size (view->throbber->frames); + + if (number_of_frames > 0) { + width = ply_throbber_get_width (view->throbber); + height = ply_throbber_get_height (view->throbber); + ply_throbber_start (view->throbber, + plugin->loop, + view->display, + screen_width / 2.0 - width / 2.0, + view->logo_area.y + view->logo_area.height + height / 2); + } + ply_progress_bar_show (view->progress_bar, + view->display, + 0, screen_height - ply_progress_bar_get_height (view->progress_bar)); + view_redraw (view); +} + +static void +view_show_prompt (view_t *view, + const char *prompt) +{ + ply_boot_splash_plugin_t *plugin; + int x, y; + int entry_width, entry_height; + + assert (view != NULL); + + plugin = view->plugin; + + if (ply_entry_is_hidden (view->entry)) { + unsigned long screen_width, screen_height; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + view->box_area.width = ply_image_get_width (plugin->box_image); + view->box_area.height = ply_image_get_height (plugin->box_image); + view->box_area.x = screen_width / 2.0 - view->box_area.width / 2.0; + view->box_area.y = screen_height / 2.0 - view->box_area.height / 2.0; + + view->lock_area.width = ply_image_get_width (plugin->lock_image); + view->lock_area.height = ply_image_get_height (plugin->lock_image); + + entry_width = ply_entry_get_width (view->entry); + entry_height = ply_entry_get_height (view->entry); + + x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0 + view->lock_area.width; + y = screen_height / 2.0 - entry_height / 2.0; + + view->lock_area.x = screen_width / 2.0 - (view->lock_area.width + entry_width) / 2.0; + view->lock_area.y = screen_height / 2.0 - view->lock_area.height / 2.0; + + ply_entry_show (view->entry, plugin->loop, view->display, x, y); + } + + if (prompt != NULL) { + ply_label_set_text (view->label, prompt); + + x = view->box_area.x + view->lock_area.width / 2; + y = view->box_area.y + view->box_area.height; + + ply_label_show (view->label, view->display, x, y); + } +} + +static void +view_hide_prompt (view_t *view) +{ + assert (view != NULL); + + ply_entry_hide (view->entry); + ply_label_hide (view->label); +} + +static ply_boot_splash_plugin_t * +create_plugin (ply_key_file_t *key_file) +{ + ply_boot_splash_plugin_t *plugin; + char *image_dir, *image_path; + char *color; + + srand ((int) ply_get_timestamp ()); + plugin = calloc (1, sizeof(ply_boot_splash_plugin_t)); + + image_dir = ply_key_file_get_value (key_file, "calculate", "ImageDir"); + + plugin->logo_image = NULL; + plugin->boot_image = ply_key_file_get_value (key_file, "calculate", "BootImage"); + plugin->shutdown_image = ply_key_file_get_value (key_file, "calculate", "ShutdownImage"); + + plugin->shutdown_font = ply_key_file_get_value (key_file, "calculate", "ShutdownFont"); + plugin->shutdown_text = ply_key_file_get_value (key_file, "calculate", "ShutdownText"); + color = ply_key_file_get_value (key_file, "calculate", "ShutdownTextColor"); + if (color != NULL) + plugin->shutdown_color = strtol (color, NULL, 0); + else + plugin->shutdown_color = 0xffffff; + free(color); + + if (asprintf (&image_path, "%s/lock.png", image_dir) != -1) { + plugin->lock_image = ply_image_new (image_path); + free (image_path); + } + + if (asprintf (&image_path, "%s/box.png", image_dir) != -1) { + plugin->box_image = ply_image_new (image_path); + free (image_path); + } + + plugin->image_dir = image_dir; + plugin->views = ply_list_new (); + + color = ply_key_file_get_value (key_file, "calculate", "BackgroundStartColor"); + + if (color != NULL) + plugin->background_start_color = strtol (color, NULL, 0); + else + plugin->background_start_color = 0x000000; + + free (color); + + color = ply_key_file_get_value (key_file, "calculate", "BackgroundEndColor"); + + if (color != NULL) + plugin->background_end_color = strtol (color, NULL, 0); + else + plugin->background_end_color = 0x000000; + + free (color); + + color = ply_key_file_get_value (key_file, "calculate", "ProgressbarColor"); + + if (color != NULL) + plugin->progressbar_color = strtol (color, NULL, 0); + else + plugin->progressbar_color = 0xffffff; + + free (color); + + return plugin; +} + +static void +destroy_plugin (ply_boot_splash_plugin_t *plugin) +{ + if (plugin == NULL) + return; + + ply_trace ("destroying plugin"); + + if (plugin->loop != NULL) { + ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + plugin); + detach_from_event_loop (plugin); + } + + ply_image_free (plugin->logo_image); + ply_image_free (plugin->box_image); + ply_image_free (plugin->lock_image); + + + free (plugin->boot_image); + free (plugin->shutdown_image); + free (plugin->shutdown_text); + free (plugin->shutdown_font); + + free_views (plugin); + + free (plugin); +} + +static void +draw_background (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) +{ + ply_boot_splash_plugin_t *plugin; + ply_rectangle_t area; + + plugin = view->plugin; + + area.x = x; + area.y = y; + area.width = width; + area.height = height; + + if (plugin->background_start_color != plugin->background_end_color) + ply_pixel_buffer_fill_with_gradient (pixel_buffer, &area, + plugin->background_start_color, + plugin->background_end_color); + else + ply_pixel_buffer_fill_with_hex_color (pixel_buffer, &area, + plugin->background_start_color); +} + +static void +draw_logo (view_t *view, + ply_pixel_buffer_t *pixel_buffer) +{ + ply_boot_splash_plugin_t *plugin; + uint32_t *logo_data; + unsigned long screen_width, screen_height; + long width, height; + char *image_path; + + plugin = view->plugin; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + if(plugin->logo_image == NULL) { + ply_trace ("loading logo image"); + int xres = screen_width; + int yres = screen_height; + + if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN && plugin->shutdown_image) { + image_path = detect_image(plugin->shutdown_image, xres, yres); + plugin->logo_image = ply_image_new (image_path); + free (image_path); + if (!ply_image_load (plugin->logo_image)) + return; + } else if (plugin->mode == PLY_BOOT_SPLASH_MODE_BOOT_UP && plugin->boot_image) { + image_path = detect_image(plugin->boot_image, xres, yres); + plugin->logo_image = ply_image_new (image_path); + free (image_path); + if (!ply_image_load (plugin->logo_image)) + return; + } else { + plugin->logo_image = ply_image_new (""); + } + + } + + if(ply_image_get_buffer(plugin->logo_image)) { + width = ply_image_get_width (plugin->logo_image); + height = ply_image_get_height (plugin->logo_image); + logo_data = ply_image_get_data (plugin->logo_image); + view->logo_area.x = (screen_width / 2) - (width / 2); + view->logo_area.y = (screen_height / 2) - (height / 2); + view->logo_area.width = width; + view->logo_area.height = height; + + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->logo_area, + logo_data); + } +} + +static void +start_animation (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + if (plugin->is_animating) + return; + + ply_trace ("starting animation"); + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_start_animation (view); + + node = next_node; + } + + plugin->is_animating = true; + + if (plugin->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN) + plugin->is_idle = true; +} + +static void +stop_animation (ply_boot_splash_plugin_t *plugin, + ply_trigger_t *trigger) +{ + ply_list_node_t *node; + + assert (plugin != NULL); + assert (plugin->loop != NULL); + + if (!plugin->is_animating) + return; + + ply_trace ("stopping animation%s", + trigger != NULL ? " with trigger" : ""); + + plugin->is_animating = false; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_progress_bar_hide (view->progress_bar); + if (trigger != NULL) + ply_trigger_ignore_next_pull (trigger); + ply_throbber_stop (view->throbber, trigger); + + node = next_node; + } + + if (trigger != NULL) + ply_trigger_pull (trigger, NULL); +} + +static void +detach_from_event_loop (ply_boot_splash_plugin_t *plugin) +{ + plugin->loop = NULL; +} + +static void +on_draw (view_t *view, + ply_pixel_buffer_t *pixel_buffer, + int x, + int y, + int width, + int height) +{ + ply_boot_splash_plugin_t *plugin; + + plugin = view->plugin; + + draw_background (view, pixel_buffer, x, y, width, height); + + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY || + plugin->state == PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY) { + uint32_t *box_data, *lock_data; + + box_data = ply_image_get_data (plugin->box_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->box_area, + box_data); + ply_entry_draw_area (view->entry, pixel_buffer, x, y, width, height); + ply_label_draw_area (view->label, pixel_buffer, x, y, width, height); + lock_data = ply_image_get_data (plugin->lock_image); + ply_pixel_buffer_fill_with_argb32_data (pixel_buffer, + &view->lock_area, + lock_data); + } else { + draw_logo (view, pixel_buffer); + ply_throbber_draw_area (view->throbber, + pixel_buffer, x, y, width, height); + ply_progress_bar_draw_area_color (view->progress_bar, + pixel_buffer, x, y, width, height, + plugin->progressbar_color); + } + ply_label_draw_area (view->message_label, + pixel_buffer, + x, y, width, height); + + ply_label_draw_area (view->shutdown_label, + pixel_buffer, + x, y, width, height); +} + +static void +add_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + view_t *view; + + ply_trace ("adding pixel display to plugin"); + view = view_new (plugin, display); + + ply_pixel_display_set_draw_handler (view->display, + (ply_pixel_display_draw_handler_t) + on_draw, view); + + if (plugin->is_visible) { + if (view_load (view)) + ply_list_append_data (plugin->views, view); + else + view_free (view); + } else { + ply_list_append_data (plugin->views, view); + } +} + +static void +remove_pixel_display (ply_boot_splash_plugin_t *plugin, + ply_pixel_display_t *display) +{ + ply_list_node_t *node; + + ply_trace ("removing pixel display from plugin"); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + view_t *view; + ply_list_node_t *next_node; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + if (view->display == display) { + ply_pixel_display_set_draw_handler (view->display, NULL, NULL); + view_free (view); + ply_list_remove_node (plugin->views, node); + return; + } + + node = next_node; + } +} + +static bool +show_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop, + ply_buffer_t *boot_buffer, + ply_boot_splash_mode_t mode) +{ + assert (plugin != NULL); + //assert (plugin->logo_image != NULL); + + plugin->loop = loop; + plugin->mode = mode; + + ply_trace ("loading lock image"); + if (!ply_image_load (plugin->lock_image)) + return false; + + ply_trace ("loading box image"); + if (!ply_image_load (plugin->box_image)) + return false; + + if (!load_views (plugin)) { + ply_trace ("couldn't load views"); + return false; + } + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + plugin); + + ply_trace ("starting boot animation"); + start_animation (plugin); + + plugin->is_visible = true; + + return true; +} + +static void +update_status (ply_boot_splash_plugin_t *plugin, + const char *status) +{ + assert (plugin != NULL); +} + +static void +on_boot_progress (ply_boot_splash_plugin_t *plugin, + double duration, + double percent_done) +{ + ply_list_node_t *node; + double total_duration; + + if (plugin->mode == PLY_BOOT_SPLASH_MODE_UPDATES) + return; + + total_duration = duration / percent_done; + + /* Fun made-up smoothing function to make the growth asymptotic: + * fraction(time,estimate)=1-2^(-(time^1.45)/estimate) */ + percent_done = 1.0 - pow (2.0, -pow (duration, 1.45) / total_duration) * (1.0 - percent_done); + + node = ply_list_get_first_node (plugin->views); + + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + ply_progress_bar_set_percent_done (view->progress_bar, percent_done); + ply_progress_bar_draw (view->progress_bar); + + node = next_node; + } +} + +static void +hide_splash_screen (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop) +{ + assert (plugin != NULL); + + ply_trace ("hiding splash"); + if (plugin->loop != NULL) { + stop_animation (plugin, NULL); + + ply_event_loop_stop_watching_for_exit (plugin->loop, (ply_event_loop_exit_handler_t) + detach_from_event_loop, + plugin); + detach_from_event_loop (plugin); + } + + plugin->is_visible = false; +} + +static void +show_password_prompt (ply_boot_splash_plugin_t *plugin, + const char *text, + int number_of_bullets) +{ + ply_list_node_t *node; + + ply_trace ("showing password prompt"); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_show_prompt (view, text); + ply_entry_set_bullet_count (view->entry, number_of_bullets); + + node = next_node; + } +} + +static void +show_prompt (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text) +{ + ply_list_node_t *node; + + ply_trace ("showing prompt"); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_show_prompt (view, prompt); + ply_entry_set_text (view->entry, entry_text); + + node = next_node; + } +} + +static void +on_root_mounted (ply_boot_splash_plugin_t *plugin) +{ + ply_trace ("root filesystem mounted"); + plugin->root_is_mounted = true; +} + +static void +become_idle (ply_boot_splash_plugin_t *plugin, + ply_trigger_t *idle_trigger) +{ + ply_trace ("deactivation requested"); + if (plugin->is_idle) { + ply_trace ("plugin is already idle"); + ply_trigger_pull (idle_trigger, NULL); + return; + } + + stop_animation (plugin, idle_trigger); + plugin->is_idle = true; +} + +static void +hide_prompt (ply_boot_splash_plugin_t *plugin) +{ + ply_list_node_t *node; + + ply_trace ("hiding prompt"); + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + + view_hide_prompt (view); + + node = next_node; + } +} + + +static void +show_message (ply_boot_splash_plugin_t *plugin, + const char *message) +{ + ply_trace ("Showing message '%s'", message); + ply_list_node_t *node; + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + ply_label_set_text (view->message_label, message); + ply_label_show (view->message_label, view->display, 10, 10); + + ply_pixel_display_draw_area (view->display, 10, 10, + ply_label_get_width (view->message_label), + ply_label_get_height (view->message_label)); + node = next_node; + } +} + +static void +display_normal (ply_boot_splash_plugin_t *plugin) +{ + pause_views (plugin); + if (plugin->state != PLY_BOOT_SPLASH_DISPLAY_NORMAL) + hide_prompt (plugin); + + plugin->state = PLY_BOOT_SPLASH_DISPLAY_NORMAL; + start_animation (plugin); + redraw_views (plugin); + unpause_views (plugin); +} + +static void +display_password (ply_boot_splash_plugin_t *plugin, + const char *prompt, + int bullets) +{ + pause_views (plugin); + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) + stop_animation (plugin, NULL); + + plugin->state = PLY_BOOT_SPLASH_DISPLAY_PASSWORD_ENTRY; + show_password_prompt (plugin, prompt, bullets); + redraw_views (plugin); + unpause_views (plugin); +} + +static void +display_question (ply_boot_splash_plugin_t *plugin, + const char *prompt, + const char *entry_text) +{ + pause_views (plugin); + if (plugin->state == PLY_BOOT_SPLASH_DISPLAY_NORMAL) + stop_animation (plugin, NULL); + + plugin->state = PLY_BOOT_SPLASH_DISPLAY_QUESTION_ENTRY; + show_prompt (plugin, prompt, entry_text); + redraw_views (plugin); + unpause_views (plugin); +} + +static void +display_message (ply_boot_splash_plugin_t *plugin, + const char *message) +{ + show_message (plugin, message); +} + +static void +system_update (ply_boot_splash_plugin_t *plugin, + int progress) +{ + ply_list_node_t *node; + + if (plugin->mode != PLY_BOOT_SPLASH_MODE_UPDATES) + return; + + node = ply_list_get_first_node (plugin->views); + while (node != NULL) { + ply_list_node_t *next_node; + view_t *view; + + view = ply_list_node_get_data (node); + next_node = ply_list_get_next_node (plugin->views, node); + ply_progress_bar_set_percent_done (view->progress_bar, (double) progress / 100.f); + ply_progress_bar_draw (view->progress_bar); + node = next_node; + } +} + +ply_boot_splash_plugin_interface_t * +ply_boot_splash_plugin_get_interface (void) +{ + static ply_boot_splash_plugin_interface_t plugin_interface = + { + .create_plugin = create_plugin, + .destroy_plugin = destroy_plugin, + .add_pixel_display = add_pixel_display, + .remove_pixel_display = remove_pixel_display, + .show_splash_screen = show_splash_screen, + .update_status = update_status, + .on_boot_progress = on_boot_progress, + .hide_splash_screen = hide_splash_screen, + .on_root_mounted = on_root_mounted, + .become_idle = become_idle, + .display_normal = display_normal, + .display_password = display_password, + .display_question = display_question, + .display_message = display_message, + .system_update = system_update, + }; + + return &plugin_interface; +} + +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ + +#define FRAMES_PER_SECOND 30 + +ply_progress_bar_t * +ply_progress_bar_new (void) +{ + ply_progress_bar_t *progress_bar; + + progress_bar = calloc (1, sizeof(ply_progress_bar_t)); + + progress_bar->is_hidden = true; + progress_bar->percent_done = 0.0; + progress_bar->area.x = 0; + progress_bar->area.y = 0; + progress_bar->area.width = 0; + progress_bar->area.height = BAR_HEIGHT; + + return progress_bar; +} diff --git a/sys-boot/plymouth-calculate-plugin/plymouth-calculate-plugin-0.9.4.ebuild b/sys-boot/plymouth-calculate-plugin/plymouth-calculate-plugin-0.9.4.ebuild new file mode 100644 index 000000000..eb6b2c7f4 --- /dev/null +++ b/sys-boot/plymouth-calculate-plugin/plymouth-calculate-plugin-0.9.4.ebuild @@ -0,0 +1,113 @@ +# Copyright 1999-2018 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 + +inherit flag-o-matic + +MY_P=plymouth-${PV} + +if [[ ${PV} == 9999 ]]; then + inherit git-r3 + EGIT_REPO_URI="https://anongit.freedesktop.org/git/plymouth" +else + SRC_URI="${SRC_URI} https://www.freedesktop.org/software/plymouth/releases/${MY_P}.tar.xz" + KEYWORDS="~alpha amd64 ~arm ~ia64 ~ppc ~ppc64 ~sparc x86" +fi + +inherit autotools readme.gentoo-r1 systemd toolchain-funcs + +DESCRIPTION="Calculate plugin for plymouth" +HOMEPAGE="https://www.calculate-linux.org" + +LICENSE="GPL-2" +SLOT="0" +IUSE="" + +CDEPEND=" + >=media-libs/libpng-1.2.16:= + dev-libs/glib:2 + >=x11-libs/gtk+-3.14:3 + x11-libs/cairo + x11-libs/libdrm[libkms] + >=x11-libs/pango-1.21 +" +DEPEND="${CDEPEND} + app-text/docbook-xsl-stylesheets + dev-libs/libxslt + virtual/pkgconfig +" +RDEPEND="${CDEPEND} + ~sys-boot/plymouth-0.9.4 + virtual/udev + !