From ae48268a110722927cc9deb2f667f6327634436c Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 15 Jun 2020 10:22:20 -0400 Subject: [PATCH 1/2] Revert "throbgress: Remove the throbgress plugin" This reverts commit a76638856d600496f8f69b308fbcf7d623430851. --- configure.ac | 1 + src/plugins/splash/Makefile.am | 2 +- src/plugins/splash/throbgress/Makefile.am | 28 + src/plugins/splash/throbgress/plugin.c | 980 ++++++++++++++++++++++ 4 files changed, 1010 insertions(+), 1 deletion(-) create mode 100644 src/plugins/splash/throbgress/Makefile.am create mode 100644 src/plugins/splash/throbgress/plugin.c diff --git a/configure.ac b/configure.ac index d34245a..970e19f 100644 --- a/configure.ac +++ b/configure.ac @@ -280,60 +280,61 @@ plymouththemedir=$datadir/plymouth/themes AS_AC_EXPAND(PLYMOUTH_THEME_PATH, $plymouththemedir) plymouthruntimethemedir=$plymouthruntimedir/themes AS_AC_EXPAND(PLYMOUTH_RUNTIME_THEME_PATH, $plymouthruntimethemedir) plymouthplugindir=$libdir/plymouth/ AS_AC_EXPAND(PLYMOUTH_PLUGIN_PATH, $plymouthplugindir) plymouthpolicydir=$datadir/plymouth/ AS_AC_EXPAND(PLYMOUTH_POLICY_DIR, $plymouthpolicydir) plymouthconfdir=$sysconfdir/plymouth/ AS_AC_EXPAND(PLYMOUTH_CONF_DIR, $plymouthconfdir) AS_AC_EXPAND(PLYMOUTH_LIBDIR, $libdir) AS_AC_EXPAND(PLYMOUTH_LIBEXECDIR, $libexecdir) AS_AC_EXPAND(PLYMOUTH_DATADIR, $datadir) AC_CONFIG_FILES([Makefile po/Makefile.in src/libply/Makefile src/libply-splash-core/Makefile src/libply-splash-graphics/Makefile src/ply-splash-core.pc src/ply-splash-graphics.pc src/plugins/Makefile src/plugins/renderers/Makefile src/plugins/renderers/frame-buffer/Makefile src/plugins/renderers/drm/Makefile src/plugins/renderers/x11/Makefile src/plugins/splash/Makefile + src/plugins/splash/throbgress/Makefile src/plugins/splash/fade-throbber/Makefile src/plugins/splash/tribar/Makefile src/plugins/splash/text/Makefile src/plugins/splash/details/Makefile src/plugins/splash/space-flares/Makefile src/plugins/splash/two-step/Makefile src/plugins/splash/script/Makefile src/plugins/controls/Makefile src/plugins/controls/label/Makefile src/Makefile src/client/ply-boot-client.pc src/client/Makefile src/upstart-bridge/Makefile themes/Makefile themes/spinfinity/Makefile themes/fade-in/Makefile themes/tribar/Makefile themes/text/Makefile themes/details/Makefile themes/solar/Makefile themes/glow/Makefile themes/spinner/Makefile themes/script/Makefile themes/bgrt/Makefile images/Makefile scripts/plymouth-generate-initrd scripts/plymouth-populate-initrd scripts/plymouth-set-default-theme scripts/Makefile systemd-units/plymouth-halt.service diff --git a/src/plugins/splash/Makefile.am b/src/plugins/splash/Makefile.am index d167530..a19197b 100644 --- a/src/plugins/splash/Makefile.am +++ b/src/plugins/splash/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = fade-throbber text details space-flares two-step script tribar +SUBDIRS = throbgress fade-throbber text details space-flares two-step script tribar MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/splash/throbgress/Makefile.am b/src/plugins/splash/throbgress/Makefile.am new file mode 100644 index 0000000..2ac1b0c --- /dev/null +++ b/src/plugins/splash/throbgress/Makefile.am @@ -0,0 +1,28 @@ +AM_CPPFLAGS = -I$(top_srcdir) \ + -I$(srcdir)/../../../libply \ + -I$(srcdir)/../../../libply-splash-core \ + -I$(srcdir)/../../../libply-splash-graphics \ + -I$(srcdir)/../../.. \ + -I$(srcdir)/../.. \ + -I$(srcdir)/.. \ + -I$(srcdir) + +plugindir = $(libdir)/plymouth +plugin_LTLIBRARIES = throbgress.la + +throbgress_la_CFLAGS = $(PLYMOUTH_CFLAGS) \ + -DPLYMOUTH_IMAGE_DIR=\"$(datadir)/plymouth/\" \ + -DPLYMOUTH_TIME_DIR=\"$(localstatedir)/lib/plymouth/\"\ + -DPLYMOUTH_LOGO_FILE=\"$(logofile)\" \ + -DPLYMOUTH_BACKGROUND_COLOR=$(background_color) \ + -DPLYMOUTH_BACKGROUND_END_COLOR=$(background_end_color) \ + -DPLYMOUTH_BACKGROUND_START_COLOR=$(background_start_color) + +throbgress_la_LDFLAGS = -module -avoid-version -export-dynamic +throbgress_la_LIBADD = $(PLYMOUTH_LIBS) \ + ../../../libply/libply.la \ + ../../../libply-splash-core/libply-splash-core.la \ + ../../../libply-splash-graphics/libply-splash-graphics.la +throbgress_la_SOURCES = $(srcdir)/plugin.c + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/plugins/splash/throbgress/plugin.c b/src/plugins/splash/throbgress/plugin.c new file mode 100644 index 0000000..86be064 --- /dev/null +++ b/src/plugins/splash/throbgress/plugin.c @@ -0,0 +1,980 @@ +/* throbgress.c - boot splash plugin + * + * Copyright (C) 2007, 2008 Red Hat, Inc. + * + * 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 + */ +#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-progress-bar.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" + +#ifndef FRAMES_PER_SECOND +#define FRAMES_PER_SECOND 30 +#endif + +#ifndef BAR_HEIGHT +#define BAR_HEIGHT 16 +#endif + +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_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; + ply_boot_splash_display_type_t state; + + uint32_t background_start_color; + uint32_t background_end_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; +}; + +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 (); + + 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); + + 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 false; + + 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; + + 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->mode == PLY_BOOT_SPLASH_MODE_REBOOT) + return; + + plugin->is_idle = false; + + 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 - BAR_HEIGHT, + screen_width, + BAR_HEIGHT); + 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)); + + plugin->logo_image = ply_image_new (PLYMOUTH_LOGO_FILE); + image_dir = ply_key_file_get_value (key_file, "throbgress", "ImageDir"); + + asprintf (&image_path, "%s/lock.png", image_dir); + plugin->lock_image = ply_image_new (image_path); + free (image_path); + + asprintf (&image_path, "%s/box.png", image_dir); + 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, "throbgress", "BackgroundStartColor"); + + if (color != NULL) + plugin->background_start_color = strtol (color, NULL, 0); + else + plugin->background_start_color = PLYMOUTH_BACKGROUND_START_COLOR; + + free (color); + + color = ply_key_file_get_value (key_file, "throbgress", "BackgroundEndColor"); + + if (color != NULL) + plugin->background_end_color = strtol (color, NULL, 0); + else + plugin->background_end_color = PLYMOUTH_BACKGROUND_END_COLOR; + + 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_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; + + plugin = view->plugin; + + screen_width = ply_pixel_display_get_width (view->display); + screen_height = ply_pixel_display_get_height (view->display); + + 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->mode == PLY_BOOT_SPLASH_MODE_REBOOT) + 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 (view->progress_bar, + pixel_buffer, x, y, width, height); + } + ply_label_draw_area (view->message_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 logo image"); + if (!ply_image_load (plugin->logo_image)) + return false; + + 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 || + plugin->mode == PLY_BOOT_SPLASH_MODE_SYSTEM_UPGRADE || + plugin->mode == PLY_BOOT_SPLASH_MODE_FIRMWARE_UPGRADE) + 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); + + 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 && + plugin->mode != PLY_BOOT_SPLASH_MODE_SYSTEM_UPGRADE && + plugin->mode != PLY_BOOT_SPLASH_MODE_FIRMWARE_UPGRADE) + 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); + 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: */ -- 2.21.0