Software/Plymouth/Scripts

This is a brief introduction to the Plymouth scripting language. The language has many points in common with Javascript and C, so if you know those languages, little should be of surprise.

Basics

There are three types of supported comments:

# script style line comments
// C++ style line comments
/* and C style block comments /* which may be nested */ */

There are some basic objects: numbers, strings, hashes, functions and null.

Simple expression operations such as must be terminated with a semicolon, e.g.

a = b;

Multiple operations can be grouped using curly “{ }” brackets, e.g.

{
 a = b;
 c = a + 8;
}

Numbers can be operated with +, -, *, / and %. Amend assignments (+=, /= etc.) are allowed, as are pre/post inc/decrement, e.g.

a *= ++b;

Strings can be appended using + (even to numbers), e.g.

a = “A” + 7 + “B”;  # gives a string “A7B”

Applying operations on incomparable operands gives a NULL, e.g.

a = “eight” / 2;  # gives a NULL

Comparisons return a number 1, for true, or 0, for false, e.g.

a = (7 >= 6); # sets a to 1
b = ("Cat" == "Dog"); # sets b to 0

Conditional execution operations, “if/else”, “while” and “for” are supported, e.g.

if (a > 0)
 {
  a--;
  b = 0;
 }
else
 a = 0

Conditions evaluate NULL, 0 and “” (empty string) to false, everything else is true, e.g.

while (a--)
 b *= a;

Or operations are lazily evaluated and return the first value that evaluates to true (And returns the first false value), e.g.

value = cached || (cached = do_lookup (index)); # if cached is already set then it is used, otherwise a lookup is executed
if (value > 0 && value < 10) valid == 1;

Hashes can be created by simply accessing their contents using a dot or [] brackets, e.g.

a.size = 1;
b = a[“size”]; # b equals 1

All hash indexing is done using strings even when using a number, e.g.

a[1] = 1;
a[“1”] = 2; # a[1] now equals 2

An auto incrementing hash can be constructed by defining a set between [] brackets, wth the indexing starting at zero, e.g.

a = [1, "c", [3, 2]]; # a[0] equals 1, a[1] equals "C", a[2][0] equals 3, a[2][1] equals 2

To define a function use the “fun” keyword, e.g.

fun functionname (index, par1, par2)
 {
  if (index == 1)
   return par1;
  else
   return par2;
 }

Functions have local variables but if a global one exists, that is used instead. You can force the use of a local even though a global already exists (and vice versa) by using the "local" and "global" hashes, e.g.

val = 1;             #global val = 1
fun functionname ()
 {
  val = 2;           #global val = 2   (global exists, so is used)
  local.val = 3;     #local  val = 3   (explicitly uses the local)
  val = 4;           #local  val = 4   (local exists, so is used)
  mval = 5;          #local mval = 5   (neither global nor local exist, so a local is created)
 }

Plymouth Interaction

There are two basic Plymouth objects: Image and Sprite.

Plymouth Images

To create a new image you need to supply the filename of the image within the theme image directory to Image, e.g.

box_image = Image ("box.png");
logo_image = Image ("special://logo");   # "special://logo" is a special keyword which finds the logo image

You can also create images from text. These are useful to show text messages, e.g.

warning_image = Image.Text ("System running FSCK. This may take some time");

The default is white text color, but you can supply additional parameters of: red, green, blue, alpha and fontname.

warning_image = Image.Text ("I feel faded", 0.8, 0.8, 0.8, 0.8, "Fixed");

The width and height of an image can be attained using GetWidth and GetHeight, e.g.

logo_area = logo_image.GetWidth() * logo_image.GetHeight();

An image can be rotated or scaled using Rotate and Scale, e.g.

upside_down_logo_image = logo_image.Rotate (3.1415); # the second paramiter is the angle in radians
fat_logo_image = logo_image.Scale (logo_image.GetWidth() * 2 , logo_image.GetHeight ()) # make the image twice the width

Plymouth Sprites

To place an image on the screen, we use sprites.

To create a new sprite call Sprite, then set the image using SetImage, e.g.

my_sprite = Sprite ();
my_sprite.SetImage (fat_logo_image);

You can also set the image while creating the sprite by supplying it to the constructor e.g.

my_sprite = Sprite (fat_logo_image);

The default placement of a new sprite is at the top left corner of the screen (at 0,0). To change the position call SetX and SetY, e.g.

my_sprite.SetX (100);
my_sprite.SetY (200);

If there are multiple sprites it us useful to decide which sprite should be shown above other. This is controlled using the Z component, the sprite with higher the Z is drawn on top.

background_sprite.SetZ (-10);
foreground_sprite.SetZ (10);

To set X, Y and Z in one call you can use SetPosition

logo_sprite.Setposition(100, 100, 0); # place at X=100, Y=100, Z=0

SetOpacity can make sprites transparent (the default opacity is solid 1) or even invisible when set to 0 , e.g.

faded_sprite.SetOpacity (0.5);
invisible_sprite.SetOpacity (0);

It is also possible to get the X/Y/Z/Opcaity/Image properties of a sprite.

sprite.SetOpacity(sprite.GetOpacity()/2);
sprite.SetPosition(sprite.GetX()+1, sprite.Gety()+1, sprite.GetZ());
sprite.SetImage(sprite.GetImage().Rotate(0.1));

Knowing the size of the window can be useful to position sprites. This can be reached using Window.GetWidth and Window.GetHeight, e.g.

centred_sprite.SetX (Window.GetWidth ()  / 2 - centred_sprite.GetImage().GetWidth()  / 2);
centred_sprite.SetY (Window.GetHeight () / 2 - centred_sprite.GetImage().GetHeight() / 2);

If the sprites do not fully cover the whole window, some of the sprite background will be exposed. To set the background colours use Window.SetBackground{Top,Bottom}Color. These take Red, Green and Blue values between 0 and 1, e.g.

Window.SetBackgroundTopColor (0, 0, 1);           # Nice blue on top of the screen fading to
Window.SetBackgroundBottomColor (0.8, 0.2, 0.1);  # an equally nice brown on the bottom

Plymouth Callbacks

Calling Plymouth.SetRefreshFunction with a function will set that function to be called up to 50 times every second, e.g.

fun refresh_callback ()
{
 time++;
}
Plymouth.SetRefreshFunction (refresh_callback);

Other callbacks which can be hooked onto are:

e.g.

fun progress_callback (time, progress)
{
 progress_status = "We have waited " + time + "seconds and we are "+ (progress * 100) + "% though";
 ...
}
Plymouth.SetBootProgressFunction (progress_callback);

To determine the mode of operation plymouth was started in use Plymouth.GetMode which returns a string of one of: "boot", "shutdown", "suspend", "resume" or unknown.

if (Plymouth.GetMode () == "suspend")
{
 ShowSuspendBackground();
}

Mathematics Functions

There are some basic mathematics functions to