mirror of
https://gitlab.freedesktop.org/plymouth/plymouth.git
synced 2026-05-08 14:48:01 +02:00
Add progress bar to spinfinity
The progress bar uses an estimate of boot time - defaulting to 45 seconds if unknown - and runs from 0% to 100% over that interval. The patch measures how long it takes to boot and writes that value to /var/lib/boottime at plugin shutdown. (This is kind of a nice side-effect - we get actual *measured* boot speed data, rather than just "feels snappier!") There's an associated script, update-boottime, that crams /var/lib/boottime into your initrd, so this splash plugin can use *that* to more closely approximate the time required to boot. This is similar to the OS X "WaitingForLoginWindow" process - see http://daringfireball.net/misc/2005/04/tiger_details#waitingforloginwindow for details on that. It's an effective placebo - startup *seems* faster with the progress bar, even though it's exactly the same. You can enable it by adding 'timebar:1' to the boot commandline. This will make it run in linear-time mode - the progress bar moves linearly from 0% to 100%. Using 'timebar:2' modifies the percentage calculation to use an exponential function - this makes the bar run faster at first, then slow as it approaches 100%. This makes startup seem even faster.
This commit is contained in:
parent
b183cdf6fe
commit
1cd0b37954
1 changed files with 109 additions and 1 deletions
|
|
@ -18,6 +18,7 @@
|
|||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by: Ray Strode <rstrode@redhat.com>
|
||||
* Will Woods <wwoods@redhat.com>
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
|
|
@ -60,11 +61,21 @@
|
|||
#define FRAMES_PER_SECOND 30
|
||||
#endif
|
||||
|
||||
#ifndef BAR_HEIGHT
|
||||
#define BAR_HEIGHT 16
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_BOOTTIME
|
||||
#define DEFAULT_BOOTTIME 45.0
|
||||
#endif
|
||||
|
||||
#define BOOTTIME_FILE "/var/lib/boottime"
|
||||
|
||||
struct _ply_boot_splash_plugin
|
||||
{
|
||||
ply_event_loop_t *loop;
|
||||
ply_frame_buffer_t *frame_buffer;
|
||||
ply_frame_buffer_area_t box_area, lock_area, logo_area;
|
||||
ply_frame_buffer_area_t box_area, lock_area, logo_area, bar_area;
|
||||
ply_image_t *logo_image;
|
||||
ply_image_t *lock_image;
|
||||
ply_image_t *box_image;
|
||||
|
|
@ -74,6 +85,11 @@ struct _ply_boot_splash_plugin
|
|||
ply_throbber_t *throbber;
|
||||
ply_label_t *label;
|
||||
|
||||
double boottime;
|
||||
double starttime;
|
||||
double waittime;
|
||||
unsigned bar_mode; /* XXX remove when we decide on a mode */
|
||||
|
||||
ply_answer_t *pending_password_answer;
|
||||
ply_trigger_t *idle_trigger;
|
||||
|
||||
|
|
@ -85,6 +101,7 @@ static void detach_from_event_loop (ply_boot_splash_plugin_t *plugin);
|
|||
ply_boot_splash_plugin_t *
|
||||
create_plugin (void)
|
||||
{
|
||||
FILE *fh;
|
||||
ply_boot_splash_plugin_t *plugin;
|
||||
|
||||
srand ((int) ply_get_timestamp ());
|
||||
|
|
@ -99,6 +116,36 @@ create_plugin (void)
|
|||
"throbber-");
|
||||
plugin->label = ply_label_new ();
|
||||
|
||||
plugin->starttime = ply_get_timestamp ();
|
||||
plugin->boottime = DEFAULT_BOOTTIME;
|
||||
/* We should be reading from the initrd at this point */
|
||||
fh = fopen(BOOTTIME_FILE,"r");
|
||||
if (fh != NULL) {
|
||||
int r;
|
||||
r = fscanf (fh,"%lf",&plugin->boottime);
|
||||
/* Don't need to check the return value - if this failed we still have
|
||||
* the default BOOTTIME value, which was set above */
|
||||
fclose (fh);
|
||||
}
|
||||
/* XXX REMOVE THIS WHEN WE DECIDE ON A PROPER METHOD */
|
||||
plugin->bar_mode = 0; /* Default to "off" */
|
||||
fh = fopen("/proc/cmdline","r");
|
||||
if (fh != NULL) {
|
||||
char cmdline[1024];
|
||||
size_t r;
|
||||
r = fread(cmdline,sizeof(char),sizeof(cmdline),fh);
|
||||
fclose(fh);
|
||||
if (r > 0) {
|
||||
if (strstr(cmdline,"timebar:0") != NULL) /* No bar */
|
||||
plugin->bar_mode = 0;
|
||||
else if (strstr(cmdline,"timebar:1") != NULL) /* Linear bar */
|
||||
plugin->bar_mode = 1;
|
||||
else if (strstr(cmdline,"timebar:2") != NULL) /* Exponential bar */
|
||||
plugin->bar_mode = 2;
|
||||
}
|
||||
}
|
||||
/* XXX END TEST CODE */
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +163,7 @@ tell_gdm_to_transition (void)
|
|||
void
|
||||
destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
FILE *boottime;
|
||||
if (plugin == NULL)
|
||||
return;
|
||||
|
||||
|
|
@ -135,6 +183,14 @@ destroy_plugin (ply_boot_splash_plugin_t *plugin)
|
|||
ply_throbber_free (plugin->throbber);
|
||||
ply_label_free (plugin->label);
|
||||
|
||||
ply_trace ("writing boottime");
|
||||
/* At this point we should have a real rootfs */
|
||||
boottime = fopen (BOOTTIME_FILE,"w");
|
||||
if (boottime != NULL) {
|
||||
fprintf (boottime,"%.1f\n", (ply_get_timestamp () - plugin->starttime));
|
||||
fclose (boottime);
|
||||
}
|
||||
|
||||
#ifdef PLY_ENABLE_GDM_TRANSITION
|
||||
if (plugin->is_visible)
|
||||
tell_gdm_to_transition ();
|
||||
|
|
@ -182,6 +238,52 @@ draw_logo (ply_boot_splash_plugin_t *plugin)
|
|||
ply_frame_buffer_unpause_updates (plugin->frame_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_bar (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
long width, height;
|
||||
double fraction;
|
||||
|
||||
height = BAR_HEIGHT; /* TODO: configurable */
|
||||
|
||||
ply_frame_buffer_get_size (plugin->frame_buffer, &plugin->bar_area);
|
||||
plugin->bar_area.x = 0; /* possibly unnecessary, but hey.. can't hurt */
|
||||
plugin->bar_area.y = plugin->bar_area.height - BAR_HEIGHT;
|
||||
plugin->bar_area.height = BAR_HEIGHT;
|
||||
/* XXX Remove when we decide on a mode */
|
||||
if (plugin->bar_mode == 1)
|
||||
fraction = (ply_get_timestamp () - plugin->starttime) / plugin->boottime;
|
||||
else /* Shouldn't get here unless bar_mode is > 0 */
|
||||
/* Fun made-up smoothing function to make the growth asymptotic:
|
||||
* fraction(time,estimate)=1-2^(-(time^1.45)/estimate) */
|
||||
fraction = 1.0-pow(2.0,-pow(ply_get_timestamp () - plugin->starttime,1.45)/plugin->boottime);
|
||||
width = (long) (plugin->bar_area.width * fraction);
|
||||
if (width < 0)
|
||||
width = 0;
|
||||
if (width < plugin->bar_area.width)
|
||||
plugin->bar_area.width = width;
|
||||
ply_frame_buffer_pause_updates (plugin->frame_buffer);
|
||||
draw_background (plugin, &plugin->bar_area);
|
||||
ply_frame_buffer_fill_with_hex_color (plugin->frame_buffer,
|
||||
&plugin->bar_area,
|
||||
0xffffff); /* white */
|
||||
ply_frame_buffer_unpause_updates (plugin->frame_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
animate_bar (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
assert (plugin != NULL);
|
||||
assert (plugin->loop != NULL);
|
||||
if (plugin->bar_mode == 0)
|
||||
return;
|
||||
draw_bar (plugin);
|
||||
ply_event_loop_watch_for_timeout(plugin->loop,
|
||||
1.0 / FRAMES_PER_SECOND,
|
||||
(ply_event_loop_timeout_handler_t)
|
||||
animate_bar, plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
start_animation (ply_boot_splash_plugin_t *plugin)
|
||||
{
|
||||
|
|
@ -203,6 +305,7 @@ start_animation (ply_boot_splash_plugin_t *plugin)
|
|||
plugin->window,
|
||||
area.width / 2.0 - width / 2.0,
|
||||
plugin->logo_area.y + plugin->logo_area.height + height / 2);
|
||||
animate_bar (plugin);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -215,6 +318,9 @@ stop_animation (ply_boot_splash_plugin_t *plugin,
|
|||
assert (plugin->loop != NULL);
|
||||
|
||||
ply_throbber_stop (plugin->throbber, trigger);
|
||||
ply_event_loop_stop_watching_for_timeout(plugin->loop,
|
||||
(ply_event_loop_timeout_handler_t)
|
||||
animate_bar, plugin);
|
||||
|
||||
#ifdef ENABLE_FADE_OUT
|
||||
for (i = 0; i < 10; i++)
|
||||
|
|
@ -281,6 +387,7 @@ on_enter (ply_boot_splash_plugin_t *plugin,
|
|||
|
||||
ply_entry_hide (plugin->entry);
|
||||
ply_entry_remove_all_bullets (plugin->entry);
|
||||
plugin->starttime += (ply_get_timestamp() - plugin->waittime);
|
||||
start_animation (plugin);
|
||||
}
|
||||
|
||||
|
|
@ -522,6 +629,7 @@ ask_for_password (ply_boot_splash_plugin_t *plugin,
|
|||
ply_answer_t *answer)
|
||||
{
|
||||
plugin->pending_password_answer = answer;
|
||||
plugin->waittime = ply_get_timestamp ();
|
||||
|
||||
if (ply_entry_is_hidden (plugin->entry))
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue