Jak sprawić, by Plymouth wyświetlał komunikaty rozruchowe podczas uruchamiania?

20

Chciałbym wiedzieć, jak utworzyć powitalny dla Ubuntu Maverick z komunikatami rozruchowymi wyświetlanymi podczas uruchamiania, a także pasek postępu i obracające się logo.

Lub, jeśli to możliwe, jak edytować panel powitalny, który ma już obracające się logo i pasek postępu, i dodawać do niego komunikaty rozruchowe.

To jest temat, który chciałbym edytować:

i chciałbym coś takiego:

wprowadź opis zdjęcia tutaj

lub to, co dokładnie chcę utworzyć:

wprowadź opis zdjęcia tutaj


udało mi się znaleźć tę stronę internetową, która zawiera wiele przydatnych informacji, ale mam trudności z jej zrozumieniem. nie robiłem wcześniej żadnego skryptu!

Utwórz własny ekran powitalny z przewijanymi komunikatami rozruchowymi

Skrypty Plymouth

i to jest kolejna strona internetowa, która może pomóc w tworzeniu skryptów

to jest skrypt dla paska postępu w widoku powitalnym:

    #----------------------------------------- Progress Bar --------------------------------

    progress_box.image = Image("progress_box.png");
    progress_box.sprite = Sprite(progress_box.image);

    progress_box.x = Window.GetX() + Window.GetWidth() / 2 - progress_box.image.GetWidth() / 2;
    progress_box.y = Window.GetY() + Window.GetHeight() * 0.65 - progress_box.image.GetHeight() / 2;
    progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 0);

    progress_bar.original_image = Image("progress_bar.png");
    progress_bar.sprite = Sprite();

    progress_bar.x = Window.GetX() + Window.GetWidth()  / 2 -        progress_bar.original_image.GetWidth() / 2;
    progress_bar.y = Window.GetY() + Window.GetHeight() * 0.65  - progress_box.image.GetHeight() / 2 + (progress_box.image.GetHeight() - progress_bar.original_image.GetHeight()) / 2;
    progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 1);

    fun progress_callback (duration, progress)
      {
        if (progress_bar.image.GetWidth () != Math.Int (progress_bar.original_image.GetWidth () * progress))
          {
# add the * 3 to multiply the speed of the progress bar by 3
            progress_bar.image = progress_bar.original_image.Scale(progress_bar.original_image.GetWidth(progress_bar.original_image) * progress * 3, progress_bar.original_image.GetHeight());
            progress_bar.sprite.SetImage (progress_bar.image);
          }
      }

    Plymouth.SetBootProgressFunction(progress_callback);

OK, więc przeprowadziłem znacznie więcej poszukiwań i mogłem dowiedzieć się nieco więcej o Plymouth.

to są strony, które uznałem za przydatne. Przewodnik tematyczny w Plymouth Istnieją cztery części tego artykułu, które musisz przeczytać, aby uzyskać sedno tego, co robimy. (Porównywałem ich skrypt ze skryptem dla mojego powitania, aby zrozumieć, co to jest, zalecam zrobienie tego, jeśli ktoś ma pójść w moje ślady.) Skrypt Plymouth Ok, ten link ma 2 strony, które musiał przejść przez nich, aby zrozumieć, co robić . Okazało się, że chodziło o to samo, co ja, czyli o przekierowanie komunikatów rozruchowych do Plymouth splash, gdzie mam już obracające się logo, tło, pasek postępu.

Musiałem więc edytować /lib/lsb/init-functionsplik i sprawić, aby wysyłał komunikaty o błędzie rozruchu / sukcesie itp. Do Plymouth poprzez dodanie tego akapitu

# SEND MESSAGES TO PLYMOUTH
if [ -x /bin/plymouth ] && pidof plymouthd >/dev/null
then
    plymouth_send() {
        [ "$1" = '-n' ] && { # add a flag '>' for lines that will be extended
            shift
            /bin/plymouth message --text=">$*" || true
            return
        }
        [ "$1" = '-w' ] && { # add "warning" formatting
            shift
            /bin/plymouth update --status="warning" || true
            /bin/plymouth message --text="$*" || true
            /bin/plymouth update --status="normal" || true
            return
        }
        [ "$1" = '-f' ] && { # add "failed" formatting
            shift
            /bin/plymouth update --status="failed" || true
            /bin/plymouth message --text="$*" || true
            /bin/plymouth update --status="normal" || true
            return
        }
        /bin/plymouth message --text="$*" || true
    }
else
    plymouth_send() { :; }
fi

# int log_begin_message (char *message)
log_begin_msg () {
    if [ -z "${1:-}" ]; then
        return 1
    fi
    echo -n "$@"
}

Jak również dodawanie

   # Only do the fancy stuff if we have an appropriate terminal
    # and if /usr is already mounted
    if log_use_fancy_output; then
        RED=`$TPUT setaf 1`
        YELLOW=`$TPUT setaf 3`
        NORMAL=`$TPUT op`
    else
        RED=''
        YELLOW=''
        NORMAL=''
    fi

    if [ $1 -eq 0 ]; then
        echo "."
        plymouth_send "."
    elif [ $1 -eq 255 ]; then
        /bin/echo -e " ${YELLOW}(warning).${NORMAL}"
        plymouth_send -w " (warning)."
    else
        /bin/echo -e " ${RED}failed!${NORMAL}"
        plymouth_send -f " failed!"
    fi
    log_end_msg_post "$@"
    return $retval
}

log_action_msg () {
    echo "$@."
    plymouth_send "$@."
}

log_action_begin_msg () {
    echo -n "$@..."
    plymouth_send -n "$@..."
}

log_action_cont_msg () {
    echo -n "$@..."
    plymouth_send -n "$@..."
}

log_action_end_msg () {
    log_action_end_msg_pre "$@"
    if [ -z "${2:-}" ]; then
        end="."
    else
        end=" ($2)."
    fi

    if [ $1 -eq 0 ]; then
        echo "done${end}"
        plymouth_send "done${end}"
    else
        if log_use_fancy_output; then
            RED=`$TPUT setaf 1`
            NORMAL=`$TPUT op`
            /bin/echo -e "${RED}failed${end}${NORMAL}"
        else
            echo "failed${end}"
            plymouth_send -f "failed${end}"
        fi
    fi
    log_action_end_msg_post "$@"
}

Do tej pory nie byłem w stanie przekazać wiadomości do Plymouth, ale lepiej zrozumiałem, jak działają skrypty Plymouth!

Nie wiem, co jeszcze mam zrobić, aby działało! mając nadzieję, że ktoś tu może mi pomóc

Och, a oto moja wersja skryptu dla Splasha , nad którym pracuję.

# INT2MIL-Ubuntu-10.10-Eng splashy like theme

Window.GetMaxWidth = fun (){
  i = 0;
  width = 0;
  while (Window.GetWidth(i)){
    width = Math.Max(width, Window.GetWidth(i));
    i++;
    }
  return width;
};

Window.GetMaxHeight = fun (){
  i = 0;
  height = 0;
  while (Window.GetHeight(i)){
    height = Math.Max(height, Window.GetHeight(i));
    i++;
    }
  return height;
};

anim.imagecount = 100;
anim.target_width =  0.2* 0.46 * Window.GetWidth();
anim.target_height =  0.2* 0.46 * Window.GetWidth();

fun RotatedImage (index){
    index = Math.Int(index);
    if (!RotatedImageCache[index])
        RotatedImageCache[index] = anim.original_image.Rotate((Math.Pi*2*index)/anim.imagecount).Scale(anim.target_width, anim.target_height);

    return RotatedImageCache[index];
    }


if (Plymouth.GetMode() == "suspend" || Plymouth.GetMode() == "resume") {
  background.original_image = ImageNew("suspend.png");
  Window.SetBackgroundTopColor(1, 0, 0);
  Window.SetBackgroundBottomColor(0, 1, 0);
}
else {
  logo.original_image = ImageNew("logo.png");
  background.original_image = ImageNew("background.png");
  Window.SetBackgroundTopColor(0.234, 0.43, 0.705);
  Window.SetBackgroundBottomColor(0.16, 0.25, 0.44);

  anim.image= ImageNew("animation.png");
  anim.original_image= anim.image.Scale(anim.target_width, anim.target_width);

  anim.sprite = SpriteNew();
  anim.sprite.SetImage(RotatedImage (0));
  anim.sprite.SetX((Window.GetX() + Window.GetWidth() - RotatedImage(0).GetWidth()) / 2);
  anim.sprite.SetY(Window.GetY() + Window.GetHeight() * 0.37);
  anim.angle = 0;
  anim.index = 0;


}
#change reduction size to make logo bigger
ratio =  logo.original_image.GetWidth() / logo.original_image.GetHeight();
reduction = 0.4;
logo.image = logo.original_image.Scale(reduction * Window.GetMaxWidth() , reduction / ratio *  Window.GetMaxWidth());
logo.sprite = SpriteNew();
logo.sprite.SetImage(logo.image);
logo.opacity_angle = 0;
#change logo location
logo.sprite.SetX((Window.GetX() + Window.GetMaxWidth()  - logo.image.GetWidth())  / 2);
logo.sprite.SetY(Window.GetY() + Window.GetHeight() * 0.37);
#background image attributs x,z,y
background.image = background.original_image.Scale(Window.GetMaxWidth() , Window.GetMaxHeight());
background.sprite = SpriteNew();
background.sprite.SetImage(background.image);
background.sprite.SetPosition(Window.GetX(), Window.GetY(), -10);

sprite_prompt = SpriteNew();

fun refresh_callback ()
  {
    if (status == "normal")
      {
#anim.index=speed of rotation
    anim.index += 1;
    anim.index %= anim.imagecount;
    anim.sprite.SetImage(RotatedImage (anim.index));
        #anim.sprite.SetOpacity (1);
    motif.sprite.SetOpacity(motif.opacity);
      }
    else
      {
        anim.sprite.SetOpacity(0);
    motif.sprite.SetOpacity(0);
      }

  }

if (Plymouth.GetMode() != "suspend" && Plymouth.GetMode() != "resume") {
  Plymouth.SetRefreshFunction (refresh_callback);
}

#----------------------------------------- Dialog --------------------------------

status = "normal";

fun dialog_setup()
  {
    local.box;
    local.lock;
    local.entry;
    local.prompt_sprite;

    box.image = ImageNew("box.png");
    lock.image = ImageNew("lock.png");
    entry.image = ImageNew("entry.png");

    box.sprite = SpriteNew();
    box.sprite.SetImage(box.image);
    box.x = Window.GetX() + Window.GetWidth()  / 2 - box.image.GetWidth()/2;
    box.y = Window.GetY() + Window.GetHeight() / 2 - box.image.GetHeight()/2;
    box.z = 10000;
    box.sprite.SetPosition(box.x, box.y, box.z);

    lock.sprite = SpriteNew();
    lock.sprite.SetImage(lock.image);
    lock.x = box.x + box.image.GetWidth()/2 - (lock.image.GetWidth() + entry.image.GetWidth()) / 2;
    lock.y = box.y + box.image.GetHeight()/2 - lock.image.GetHeight()/2;
    lock.z = box.z + 1;
    lock.sprite.SetPosition(lock.x, lock.y, lock.z);

    entry.sprite = SpriteNew();
    entry.sprite.SetImage(entry.image);
    entry.x = lock.x + lock.image.GetWidth();
    entry.y = box.y + box.image.GetHeight()/2 - entry.image.GetHeight()/2;
    entry.z = box.z + 1;
    entry.sprite.SetPosition(entry.x, entry.y, entry.z);

    prompt_sprite = SpriteNew();
    prompt_sprite.SetPosition(box.x, box.y - 20, box.z);

    global.dialog.box = box;
    global.dialog.lock = lock;
    global.dialog.entry = entry;
    global.dialog.bullet_image = ImageNew("bullet.png");
    global.dialog.prompt_sprite = prompt_sprite;
    dialog_opacity (1);
  }

fun dialog_opacity(opacity)
  {
    dialog.box.sprite.SetOpacity(opacity);
    dialog.lock.sprite.SetOpacity(opacity);
    dialog.entry.sprite.SetOpacity(opacity);
    dialog.prompt_sprite.SetOpacity(opacity);
    for (index = 0; dialog.bullet[index]; index++)
      {
        dialog.bullet[index].sprite.SetOpacity(opacity);
      }
  }

fun display_normal_callback ()
  {
    global.status = "normal";
    if (global.dialog)
      dialog_opacity (0);
  }

fun display_password_callback (prompt, bullets)
  {
    global.status = "password";
    if (!global.dialog) 
    dialog_setup();
    else 
    dialog_opacity(1);
    motif.sprite.SetOpacity(0);
    anim.sprite.SetOpacity(0);

    dialog.prompt_sprite.SetImage(Image.Text(prompt, 1.0, 1.0, 1.0));
    for (index = 0; dialog.bullet[index] || index < bullets; index++)
      { 

        if (!dialog.bullet[index])
          {
            dialog.bullet[index].sprite = SpriteNew();
            dialog.bullet[index].sprite.SetImage(dialog.bullet_image);
            dialog.bullet[index].x = dialog.entry.x + index * dialog.bullet_image.GetWidth();
            dialog.bullet[index].y = dialog.entry.y + dialog.entry.image.GetHeight() / 2 - dialog.bullet_image.GetHeight() / 2;
            dialog.bullet[index].z = dialog.entry.z + 1;
            dialog.bullet[index].sprite.SetPosition(dialog.bullet[index].x, dialog.bullet[index].y, dialog.bullet[index].z);
          }
        if (index < bullets)
          dialog.bullet[index].sprite.SetOpacity(1);
        else
          dialog.bullet[index].sprite.SetOpacity(0);
      }
  }

fun display_message_callback (prompt)
  {

prompt = Image.Text(prompt,1.0, 1.0, 1.0);
sprite_prompt.SetImage(prompt);
sprite_prompt.SetPosition(Window.GetX() + (Window.GetWidth() - prompt.GetWidth()) / 2, Window.GetY() + Window.GetHeight() * 0.93, 2);
  }

/* instantiate dialog at startup, to ensure all icons are loaded in memory before initrd is unmounted, in case /usr isn't mounted yet */
dialog_setup(); dialog_opacity(0);
Plymouth.SetDisplayNormalFunction(display_normal_callback);
Plymouth.SetDisplayPasswordFunction(display_password_callback);
Plymouth.SetMessageFunction(display_message_callback);

#----------------------------------------- Progress Bar --------------------------------

progress_box.image = Image("progress_box.png");
progress_box.sprite = Sprite(progress_box.image);

progress_box.x = Window.GetX() + Window.GetWidth() / 2 - progress_box.image.GetWidth() / 2;
progress_box.y = Window.GetY() + Window.GetHeight() * 0.65 - progress_box.image.GetHeight() / 2;
progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 0);

progress_bar.original_image = Image("progress_bar.png");
progress_bar.sprite = Sprite();

progress_bar.x = Window.GetX() + Window.GetWidth()  / 2 -        progress_bar.original_image.GetWidth() / 2;
progress_bar.y = Window.GetY() + Window.GetHeight() * 0.65  - progress_box.image.GetHeight() / 2 + (progress_box.image.GetHeight() - progress_bar.original_image.GetHeight()) / 2;
progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 1);

fun progress_callback (duration, progress)
  {
    if (progress_bar.image.GetWidth () != Math.Int (progress_bar.original_image.GetWidth () * progress))
      {
        progress_bar.image = progress_bar.original_image.Scale(progress_bar.original_image.GetWidth(progress_bar.original_image) * progress * 3, progress_bar.original_image.GetHeight());
        progress_bar.sprite.SetImage (progress_bar.image);
      }
  }

Plymouth.SetBootProgressFunction(progress_callback);

#----------------------------------------- Status Update --------------------------------

NUM_SCROLL_LINES = 5;
LINE_WIDTH = 55;
# width of one character
CHAR_WIDTH = 7;
# height of one character
CHAR_HEIGHT = 10;

msg_color = [0.5,0.5,0.5]; # msg_color is array

fun update_status_callback(sta) {
  if (sta == "failed") msg_color = [1,0,0];
  if (sta == "warning") msg_color = [0.8,0.8,0];
  if (sta == "normal") msg_color = [0.5,0.5,0.5];
}

fun StringLength(string) {
  index = 0;
  str = String(string);
  while(str.CharAt(index)) index++;
  return index;
}

// Initialising text images and their positions
// 20 is the height (including line spacing) of each line
for (i=0; i < NUM_SCROLL_LINES; i++) {
  lines[i]= Image.Text("",0,0,0);
  message_sprite[i] = Sprite();
  message_sprite[i].SetX (Window.GetX() + (screen_width / 2 ) - (LINE_WIDTH * CHAR_WIDTH / 2));
  message_sprite[i].SetY (Window.GetY() + (screen_height / 2) + (logo_height /2) +(logo_height * 1.2)+ (i * CHAR_HEIGHT * 2) );
  message_sprite[i].SetZ (10000);
}

pretext = String("");

fun scroll_message_callback(text) {

 nobreak = 0;
   if (text.CharAt(0) == ">") {    # "no linebreak" flag, like "-n"
       text = text.SubString(1, StringLength(text)); # remove ">" at front
       nobreak = 1;
   }

   if (pretext == "") {

       if (nobreak == 1) pretext = text;

   // Truncate the message if too long
   if (StringLength(text) > LINE_WIDTH) {
     text = text.SubString(0, LINE_WIDTH - 3);
     text += "...";
   }

   // Shift messages one up
   for (i = 0; i < NUM_SCROLL_LINES - 1; i++) {
     lines[i] = lines[i+1];
   }
 else {    # the previous message was flagged to have no linebreak

          // Truncate the message if too long
       if (StringLength(text) > LINE_WIDTH - 5) { # leave min. 5 for pretext
         text = text.SubString(0, LINE_WIDTH - 8);
         text += "...";
       }

          # Truncate the previous message if too long
       if (StringLength(pretext) > (LINE_WIDTH - StringLength(text))) {
         pretext = pretext.SubString(0, LINE_WIDTH - StringLength(text) - 3);
         pretext += "...";
       }

       text = pretext + text;

       if (nobreak == 1) pretext = text;
       else pretext = "";

   }

   // Create the image for the latest message
#  original script had "lines[i]"   
   lines[i] = Image.Text( text, 0.5, 0.5, 0.5);

   // Re-allocate the text images to sprites
   for (i = 0; i < NUM_SCROLL_LINES; i++) {
     message_sprite[i].SetImage(lines[i]);
   }
}

Plymouth.SetUpdateStatusFunction(scroll_message_callback);

# messages get added to updates
Plymouth.SetMessageFunction(scroll_message_callback);

#----------------------------------------- Quit --------------------------------

fun quit_callback ()
{
 anim.sprite.SetOpacity (0);
  if (Plymouth.GetMode() == "shutdown") {
   motif.sprite.SetOpacity(0);
  }
}

Plymouth.SetQuitFunction(quit_callback);

OK, więc podałem prawie wszystkie potrzebne informacje, jeśli ktoś jest zaznajomiony z tym, daj mi znać, czego mi brakuje, aby przekazać komunikaty rozruchowe do Plymouth. Dzięki

Witalij
źródło
Jeśli ktoś chce przetestować splash bez ponownego uruchamiania, jest to łatwa metoda: „Zainstaluj pakiet plymouth-x11 Uruchom sudo plymouthd; sudo plymouth --show-splash; spać 10; sudo killall plymouthd ' askubuntu.com/questions/51078/…
Witalij
1
Aha i jeszcze jedną rzecz powinienem zmienić GRUB_CMDLINE_LINUX_DEFAULT = „cichy plusk” na GRUB_CMDLINE_LINUX_DEFAULT = „plusk”, aby komunikaty były wyświetlane?
Witalij
freedesktop.org/wiki/Software/Plymouth/Scripts kolejna strona skryptowa Plymouth. bardzo pomaga, jeśli nie znasz żadnego javascript lub C.
Witalij,

Odpowiedzi:

4

OK, więc pracuję nad tym problemem od 4 dni i prawie go całkowicie przybiłem. Do tej pory udało mi się zmusić Plymouth do uruchomienia z wyświetlonymi komunikatami, ale niestety wiadomości są obcinane. Obecnie próbuję ulepszyć skrypty, ale nie wiem, gdzie jest problem w skrypcie / lib / lsb / init-functions lub /lib/plymouth/themes/"theme-name"/mdv.script.

Oto moja dotychczasowa praca.

najpierw musisz ustawić funkcje inicjujące na wysyłanie wiadomości do Plymouth, tak aby wyglądało to tak (przejdź przez każdą linię, aby zobaczyć różnice i skopiuj linię odpowiadającą wysyłaniu Plymouth):

# /lib/lsb/init-functions for Debian -*- shell-script -*-
#
#Copyright (c) 2002-08 Chris Lawrence
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions
#are met:
#1. Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
#2. Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
#3. Neither the name of the author nor the names of other contributors
#   may be used to endorse or promote products derived from this software
#   without specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
#IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
#BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
#OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
#EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

start_daemon () {
    local force nice pidfile exec i args
    force=0
    nice=0
    pidfile=/dev/null

    OPTIND=1
    while getopts fn:p: opt ; do
        case "$opt" in
            f)  force=1;;
            n)  nice="$OPTARG";;
            p)  pidfile="$OPTARG";;
        esac
    done

    shift $(($OPTIND - 1))
    if [ "$1" = '--' ]; then
        shift
    fi

    exec="$1"; shift

    args="--start --nicelevel $nice --quiet --oknodo"
    if [ $force = 1 ]; then
        /sbin/start-stop-daemon $args --chdir "$PWD" --startas $exec --pidfile /dev/null -- "$@"
    elif [ $pidfile ]; then
        /sbin/start-stop-daemon $args --chdir "$PWD" --exec $exec --oknodo --pidfile "$pidfile" -- "$@"
    else
        /sbin/start-stop-daemon $args --chdir "$PWD" --exec $exec -- "$@"
    fi
}

pidofproc () {
    local pidfile line i pids= status specified pid
    pidfile=
    specified=

    OPTIND=1
    while getopts p: opt ; do
        case "$opt" in
            p)  pidfile="$OPTARG"; specified=1;;
        esac
    done
    shift $(($OPTIND - 1))

    base=${1##*/}
    if [ ! "$specified" ]; then
        pidfile="/var/run/$base.pid"
    fi

    if [ -n "${pidfile:-}" -a -r "$pidfile" ]; then
        read pid < "$pidfile"
        if [ -n "${pid:-}" ]; then
            if $(kill -0 "${pid:-}" 2> /dev/null); then
                echo "$pid"
                return 0
            elif ps "${pid:-}" >/dev/null 2>&1; then
                echo "$pid"
                return 0 # program is running, but not owned by this user
            else
                return 1 # program is dead and /var/run pid file exists
            fi
        fi
    fi
    if [ -x /bin/pidof -a ! "$specified" ]; then
        status="0"
        /bin/pidof -o %PPID -x $1 || status="$?"
        if [ "$status" = 1 ]; then
            return 3 # program is not running
        fi
        return 0
    fi
    return 4 # Unable to determine status
}

# start-stop-daemon uses the same algorithm as "pidofproc" above.
killproc () {
    local pidfile sig status base i name_param is_term_sig
    pidfile=
    name_param=
    is_term_sig=no

    OPTIND=1
    while getopts p: opt ; do
        case "$opt" in
            p)  pidfile="$OPTARG";;
        esac
    done
    shift $(($OPTIND - 1))

    base=${1##*/}
    if [ ! $pidfile ]; then
        name_param="--name $base --pidfile /var/run/$base.pid"
    else
        name_param="--pidfile $pidfile"
    fi

    sig=$(echo ${2:-} | sed -e 's/^-\(.*\)/\1/')
    sig=$(echo $sig | sed -e 's/^SIG\(.*\)/\1/')
    if [ -z "$sig" -o "$sig" = 15 -o "$sig" = TERM ]; then
        is_term_sig=yes
    fi
    status=0
    if [ ! "$is_term_sig" = yes ]; then
        if [ -n "$sig" ]; then
            /sbin/start-stop-daemon --stop --signal "$sig" --quiet $name_param || status="$?"
        else
            /sbin/start-stop-daemon --stop --quiet $name_param || status="$?"
        fi
    else
        /sbin/start-stop-daemon --stop --quiet --oknodo $name_param || status="$?"
    fi
    if [ "$status" = 1 ]; then
        if [ -n "$sig" ]; then
            return 0
        fi
        return 3 # program is not running
    fi

    if [ "$status" = 0 -a "$is_term_sig" = yes -a "$pidfile" ]; then
        pidofproc -p "$pidfile" "$1" >/dev/null || rm -f "$pidfile"
    fi
    return 0
}

# Return LSB status
status_of_proc () {
    local pidfile daemon name status

    pidfile=
    OPTIND=1
    while getopts p: opt ; do
        case "$opt" in
            p)  pidfile="$OPTARG";;
        esac
    done
    shift $(($OPTIND - 1))

    if [ -n "$pidfile" ]; then
        pidfile="-p $pidfile"
    fi
    daemon="$1"
    name="$2"

    status="0"
    pidofproc $pidfile $daemon >/dev/null || status="$?"
    if [ "$status" = 0 ]; then
        log_success_msg "$name is running"
        return 0
    elif [ "$status" = 4 ]; then
        log_failure_msg "could not access PID file for $name"
        return $status
    else
        log_failure_msg "$name is not running"
        return $status
    fi
}

log_use_fancy_output () {
    TPUT=/usr/bin/tput
    EXPR=/usr/bin/expr
    if [ -t 1 ] && [ "x${TERM:-}" != "x" ] && [ "x${TERM:-}" != "xdumb" ] && [ -x $TPUT ] && [ -x $EXPR ] && $TPUT hpa 60 >/dev/null 2>&1 && $TPUT setaf 1 >/dev/null 2>&1; then
        [ -z $FANCYTTY ] && FANCYTTY=1 || true
    else
        FANCYTTY=0
    fi
    case "$FANCYTTY" in
        1|Y|yes|true)   true;;
        *)              false;;
    esac
}

log_success_msg () {
    if [ -n "${1:-}" ]; then
        log_begin_msg $@
    fi
    log_end_msg 0
}

log_failure_msg () {
    if [ -n "${1:-}" ]; then
        log_begin_msg $@ "..."
    fi
    log_end_msg 1 || true
}

log_warning_msg () {
    if [ -n "${1:-}" ]; then
        log_begin_msg $@ "..."
    fi
    log_end_msg 255 || true
}

#
# NON-LSB HELPER FUNCTIONS
#
# int get_lsb_header_val (char *scriptpathname, char *key)
get_lsb_header_val () {
        if [ ! -f "$1" ] || [ -z "${2:-}" ]; then
                return 1
        fi
        LSB_S="### BEGIN INIT INFO"
        LSB_E="### END INIT INFO"
        sed -n "/$LSB_S/,/$LSB_E/ s/# $2: \(.*\)/\1/p" $1
}

# SEND MESSAGES TO PLYMOUTH
if [ -x /bin/plymouth ] && pidof plymouthd >/dev/null
then
    plymouth_send() {
        [ "$1" = '-n' ] && { # add a flag '>' for lines that will be extended
            shift
            /bin/plymouth message --text=">$*" || true
            return
        }
        [ "$1" = '-w' ] && { # add "warning" formatting
            shift
            /bin/plymouth update --status="warning" || true
            /bin/plymouth message --text="$*" || true
            /bin/plymouth update --status="normal" || true
            return
        }
        [ "$1" = '-f' ] && { # add "failed" formatting
            shift
            /bin/plymouth update --status="failed" || true
            /bin/plymouth message --text="$*" || true
            /bin/plymouth update --status="normal" || true
            return
        }
        /bin/plymouth message --text="$*" || true
    }
else
    plymouth_send() { :; }
fi

# int log_begin_message (char *message)
log_begin_msg () {
    if [ -z "${1:-}" ]; then
        return 1
    fi
    echo -n "$@"
    plymouth_send -n "$@"
}

# Sample usage:
# log_daemon_msg "Starting GNOME Login Manager" "gdm"
#
# On Debian, would output "Starting GNOME Login Manager: gdm"
# On Ubuntu, would output " * Starting GNOME Login Manager..."
#
# If the second argument is omitted, logging suitable for use with
# log_progress_msg() is used:
#
# log_daemon_msg "Starting remote filesystem services"
#
# On Debian, would output "Starting remote filesystem services:"
# On Ubuntu, would output " * Starting remote filesystem services..."

log_daemon_msg () {
    if [ -z "${1:-}" ]; then
        return 1
    fi
    log_daemon_msg_pre "$@"

    if [ -z "${2:-}" ]; then
        echo -n "$1:"
        plymouth_send -n "$1:"
        return
    fi

    echo -n "$1: $2"
    plymouth_send -n "$1: $2"
    log_daemon_msg_post "$@"
}

# #319739
#
# Per policy docs:
#
#     log_daemon_msg "Starting remote file system services"
#     log_progress_msg "nfsd"; start-stop-daemon --start --quiet nfsd
#     log_progress_msg "mountd"; start-stop-daemon --start --quiet mountd
#     log_progress_msg "ugidd"; start-stop-daemon --start --quiet ugidd
#     log_end_msg 0
#
# You could also do something fancy with log_end_msg here based on the
# return values of start-stop-daemon; this is left as an exercise for
# the reader...
#
# On Ubuntu, one would expect log_progress_msg to be a no-op.
log_progress_msg () {
    if [ -z "${1:-}" ]; then
        return 1
    fi
    echo -n " $@"
    plymouth_send -n " $@"
}


# int log_end_message (int exitstatus)
log_end_msg () {
    # If no arguments were passed, return
    if [ -z "${1:-}" ]; then
        return 1
    fi

    retval=$1

    log_end_msg_pre "$@"

    # Only do the fancy stuff if we have an appropriate terminal
    # and if /usr is already mounted
    if log_use_fancy_output; then
        RED=`$TPUT setaf 1`
        YELLOW=`$TPUT setaf 3`
        NORMAL=`$TPUT op`
    else
        RED=''
        YELLOW=''
        NORMAL=''
    fi

    if [ $1 -eq 0 ]; then
        echo "."
        plymouth_send "."
    elif [ $1 -eq 255 ]; then
        /bin/echo -e " ${YELLOW}(warning).${NORMAL}"
        plymouth_send -w "warning"
    else
        /bin/echo -e " ${RED}failed!${NORMAL}"
        plymouth_send -f "failed"
    fi
    log_end_msg_post "$@"
    return $retval
}

log_action_msg () {
    echo "$@."
    plymouth_send "$@."
}

log_action_begin_msg () {
    echo -n "$@..."
    plymouth_send -n "$@..."
}

log_action_cont_msg () {
    echo -n "$@..."
    plymouth_send -n "$@..."
}

log_action_end_msg () {
    log_action_end_msg_pre "$@"
    if [ -z "${2:-}" ]; then
        end="."
    else
        end=" ($2)."
    fi

    if [ $1 -eq 0 ]; then
        echo "done${end}"
        plymouth_send "done${end}"
    else
        if log_use_fancy_output; then
            RED=`$TPUT setaf 1`
            NORMAL=`$TPUT op`
            /bin/echo -e "${RED}failed${end}${NORMAL}"
            plymouth_send -f "failed${end}"
        else
            echo "failed${end}"
            plymouth_send -f "failed${end}"
        fi
    fi
    log_action_end_msg_post "$@"
}

# Hooks for /etc/lsb-base-logging.sh
log_daemon_msg_pre () { :; }
log_daemon_msg_post () { :; }
log_end_msg_pre () { :; }
log_end_msg_post () { :; }
log_action_end_msg_pre () { :; }
log_action_end_msg_post () { :; }

FANCYTTY=
[ -e /etc/lsb-base-logging.sh ] && . /etc/lsb-base-logging.sh || true

Teraz po dodaniu tego do funkcji init musisz edytować motyw Plymouth mdv.script

To jest moja najnowsza zaktualizowana wersja skryptu:

# INT2MIL-Ubuntu-10.10-Eng splashy like theme

Window.GetMaxWidth = fun (){
  i = 0;
  width = 0;
  while (Window.GetWidth(i)){
    width = Math.Max(width, Window.GetWidth(i));
    i++;
    }
  return width;
};

Window.GetMaxHeight = fun (){
  i = 0;
  height = 0;
  while (Window.GetHeight(i)){
    height = Math.Max(height, Window.GetHeight(i));
    i++;
    }
  return height;
};
#change animcount to increase/decrease speed of spinning arrows
anim.imagecount = 100;
anim.target_width =  0.2* 0.46 * Window.GetWidth();
anim.target_height =  0.2* 0.46 * Window.GetWidth();

fun RotatedImage (index){
    index = Math.Int(index);
    if (!RotatedImageCache[index])
        RotatedImageCache[index] = anim.original_image.Rotate((Math.Pi*2*index)/anim.imagecount).Scale(anim.target_width, anim.target_height);

    return RotatedImageCache[index];
    }


if (Plymouth.GetMode() == "suspend" || Plymouth.GetMode() == "resume") {
  background.original_image = ImageNew("suspend.png");
  Window.SetBackgroundTopColor(1, 0, 0);
  Window.SetBackgroundBottomColor(0, 1, 0);
}
else {
  logo.original_image = ImageNew("logo.png");
  background.original_image = ImageNew("background.png");
  Window.SetBackgroundTopColor(0.234, 0.43, 0.705);
  Window.SetBackgroundBottomColor(0.16, 0.25, 0.44);

  anim.image= ImageNew("animation.png");
  anim.original_image= anim.image.Scale(anim.target_width, anim.target_width);

  anim.sprite = SpriteNew();
  anim.sprite.SetImage(RotatedImage (0));
  anim.sprite.SetX((Window.GetX() + Window.GetWidth() - RotatedImage(0).GetWidth()) / 2);
  anim.sprite.SetY(Window.GetY() + Window.GetHeight() * 0.37);
  anim.angle = 0;
  anim.index = 0;


}
#change reduction size to make logo bigger
ratio =  logo.original_image.GetWidth() / logo.original_image.GetHeight();
reduction = 0.4;
logo.image = logo.original_image.Scale(reduction * Window.GetMaxWidth() , reduction / ratio *  Window.GetMaxWidth());
logo.sprite = SpriteNew();
logo.sprite.SetImage(logo.image);
logo.opacity_angle = 0;
#change logo location
logo.sprite.SetX((Window.GetX() + Window.GetMaxWidth()  - logo.image.GetWidth())  / 2);
logo.sprite.SetY(Window.GetY() + Window.GetHeight() * 0.37);
#background image attributs x,z,y
background.image = background.original_image.Scale(Window.GetMaxWidth() , Window.GetMaxHeight());
background.sprite = SpriteNew();
background.sprite.SetImage(background.image);
background.sprite.SetPosition(Window.GetX(), Window.GetY(), -100);

sprite_prompt = SpriteNew();

fun refresh_callback ()
  {
    if (status == "normal")
      {
#anim.index=speed of rotation
    anim.index += 1;
    anim.index %= anim.imagecount;
    anim.sprite.SetImage(RotatedImage (anim.index));
        #anim.sprite.SetOpacity (1);
    motif.sprite.SetOpacity(motif.opacity);
      }
    else
      {
        anim.sprite.SetOpacity(1);
    motif.sprite.SetOpacity(1);
      }

  }

if (Plymouth.GetMode() != "suspend" && Plymouth.GetMode() != "resume") {
  Plymouth.SetRefreshFunction (refresh_callback);
}

#----------------------------------------- Dialog --------------------------------

status = "normal";

fun dialog_setup()
  {
    local.box;
    local.lock;
    local.entry;
    local.prompt_sprite;

    box.image = ImageNew("box.png");
    lock.image = ImageNew("lock.png");
    entry.image = ImageNew("entry.png");

    box.sprite = SpriteNew();
    box.sprite.SetImage(box.image);
    box.x = Window.GetX() + Window.GetWidth()  / 2 - box.image.GetWidth()/2;
    box.y = Window.GetY() + Window.GetHeight() / 2 - box.image.GetHeight()/2;
    box.z = 10000;
    box.sprite.SetPosition(box.x, box.y, box.z);

    lock.sprite = SpriteNew();
    lock.sprite.SetImage(lock.image);
    lock.x = box.x + box.image.GetWidth()/2 - (lock.image.GetWidth() + entry.image.GetWidth()) / 2;
    lock.y = box.y + box.image.GetHeight()/2 - lock.image.GetHeight()/2;
    lock.z = box.z + 1;
    lock.sprite.SetPosition(lock.x, lock.y, lock.z);

    entry.sprite = SpriteNew();
    entry.sprite.SetImage(entry.image);
    entry.x = lock.x + lock.image.GetWidth();
    entry.y = box.y + box.image.GetHeight()/2 - entry.image.GetHeight()/2;
    entry.z = box.z + 1;
    entry.sprite.SetPosition(entry.x, entry.y, entry.z);

    prompt_sprite = SpriteNew();
    prompt_sprite.SetPosition(box.x, box.y - 20, box.z);

    global.dialog.box = box;
    global.dialog.lock = lock;
    global.dialog.entry = entry;
    global.dialog.bullet_image = ImageNew("bullet.png");
    global.dialog.prompt_sprite = prompt_sprite;
    dialog_opacity (1);
  }

fun dialog_opacity(opacity)
  {
    dialog.box.sprite.SetOpacity(opacity);
    dialog.lock.sprite.SetOpacity(opacity);
    dialog.entry.sprite.SetOpacity(opacity);
    dialog.prompt_sprite.SetOpacity(opacity);
    for (index = 0; dialog.bullet[index]; index++)
      {
        dialog.bullet[index].sprite.SetOpacity(opacity);
      }
  }

fun display_normal_callback ()
  {
    global.status = "normal";
    if (global.dialog)
      dialog_opacity (0);
  }

fun display_password_callback (prompt, bullets)
  {
    global.status = "password";
    if (!global.dialog) 
    dialog_setup();
    else 
    dialog_opacity(1);
    motif.sprite.SetOpacity(1);
    anim.sprite.SetOpacity(1);

    dialog.prompt_sprite.SetImage(Image.Text(prompt, 1.0, 1.0, 1.0));
    for (index = 0; dialog.bullet[index] || index < bullets; index++)
      { 

        if (!dialog.bullet[index])
          {
            dialog.bullet[index].sprite = SpriteNew();
            dialog.bullet[index].sprite.SetImage(dialog.bullet_image);
            dialog.bullet[index].x = dialog.entry.x + index * dialog.bullet_image.GetWidth();
            dialog.bullet[index].y = dialog.entry.y + dialog.entry.image.GetHeight() / 2 - dialog.bullet_image.GetHeight() / 2;
            dialog.bullet[index].z = dialog.entry.z + 1;
            dialog.bullet[index].sprite.SetPosition(dialog.bullet[index].x, dialog.bullet[index].y, dialog.bullet[index].z);
          }
        if (index < bullets)
          dialog.bullet[index].sprite.SetOpacity(1);
        else
          dialog.bullet[index].sprite.SetOpacity(0);
      }
  }

fun display_message_callback (prompt)
  {

prompt = Image.Text(prompt,1.0, 1.0, 1.0);
sprite_prompt.SetImage(prompt);
sprite_prompt.SetPosition(Window.GetX() + (Window.GetWidth() - prompt.GetWidth()) / 2, Window.GetY() + Window.GetHeight() * 0.93, 2);
  }

/* instantiate dialog at startup, to ensure all icons are loaded in memory before initrd is unmounted, in case /usr isn't mounted yet */
dialog_setup(); dialog_opacity(0);
Plymouth.SetDisplayNormalFunction(display_normal_callback);
Plymouth.SetDisplayPasswordFunction(display_password_callback);
Plymouth.SetMessageFunction(display_message_callback);

#----------------------------------------- Progress Bar --------------------------------

progress_box.image = Image("progress_box.png");
progress_box.sprite = Sprite(progress_box.image);

progress_box.x = Window.GetX() + Window.GetWidth() / 2 - progress_box.image.GetWidth() / 2;
progress_box.y = Window.GetY() + Window.GetHeight() * 0.65 - progress_box.image.GetHeight() / 2;
progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 0);

progress_bar.original_image = Image("progress_bar.png");
progress_bar.sprite = Sprite();

progress_bar.x = Window.GetX() + Window.GetWidth()  / 2 -        progress_bar.original_image.GetWidth() / 2;
progress_bar.y = Window.GetY() + Window.GetHeight() * 0.65  - progress_box.image.GetHeight() / 2 + (progress_box.image.GetHeight() - progress_bar.original_image.GetHeight()) / 2;
progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 1);

fun progress_callback (duration, progress)
  {
    if (progress_bar.image.GetWidth () != Math.Int (progress_bar.original_image.GetWidth () * progress))
      {
# * 3 = multiply progress by 3
        progress_bar.image = progress_bar.original_image.Scale(progress_bar.original_image.GetWidth(progress_bar.original_image) * progress * 3, progress_bar.original_image.GetHeight());
        progress_bar.sprite.SetImage (progress_bar.image);
      }
  }

Plymouth.SetBootProgressFunction(progress_callback);

#----------------------------------------- Status Update --------------------------------

NUM_SCROLL_LINES=10;
LINE_WIDTH=55;

# width of one character doesnt work------------
CHAR_WIDTH = 7;
# height of one character
CHAR_HEIGHT = 10; 
#------------------------

msg_color = [1,1,1]; # msg_color is array

#status callback function

fun update_status_callback(sta) {
  if (sta == "failed") msg_color = [1,0,0];
  if (sta == "warning") msg_color = [0.8,0.8,0];
  if (sta == "normal") msg_color = [0.5,0.5,0.5];
}

screen_width = Window.GetWidth();
screen_height = Window.GetHeight();

#Initialising text images and their positions
# 20 is the height (including line spacing) of each line

for (i=0; i < NUM_SCROLL_LINES; i++) {
  lines[i]= Image.Text("", msg_color[0], msg_color[1], msg_color[2]);
  message_sprite[i] = Sprite();
  message_sprite[i].SetPosition(screen_width * 0.025, (screen_height * 0.6) + (i * 20), 10000);
}

fun StringLength(string) {

  index = 0;
  str = String(string);
  while(str.CharAt(index)) index++;
  return index;
}

pretext = String("");

#scroll message function

fun scroll_message_callback(text) {

 ##nobreak function 

  nobreak = 0;
   if (text.CharAt(0) == ">") {    # "no linebreak" flag, like "-n"
       text = text.SubString(1, StringLength(text)); # remove ">" at front
       nobreak = 1;
   }

   if ((pretext == "") || (StringLength(text) > 15))  {
   if (text == ".") return;    # ignore messages of only a single dot

       if (nobreak == 1) pretext = text;



#Truncate the message if too long


   if (StringLength(text) > LINE_WIDTH) {
     text = text.SubString(0, LINE_WIDTH - 0);
     text += "...";
   }




#Shift message one up

   for (i = 0; i < NUM_SCROLL_LINES - 1; i++) {
     lines[i] = lines[i+1];
   }


}
   else {    # the previous message was flagged to have no linebreak

          // Truncate the message if too long
       if (StringLength(text) > LINE_WIDTH - 5) { # leave min. 5 for pretext
         text = text.SubString(0, LINE_WIDTH - 8);
         text += "...";
       }

          # Truncate the previous message if too long
       if (StringLength(pretext) > (LINE_WIDTH - StringLength(text))) {
         pretext = pretext.SubString(0, LINE_WIDTH - StringLength(text) - 3);
         pretext += "...";
       }

       text = pretext + text;

       if (nobreak == 1) pretext = text;
       else pretext = ">";

   }


#Create the image for the latest message

     lines[i] = Image.Text(text, msg_color[0], msg_color[1], msg_color[2]);

#Re-positioning the text images

  for (i = 0; i < NUM_SCROLL_LINES; i++) {
     message_sprite[i].SetImage(lines[i]);
   }
}

 Plymouth.SetUpdateStatusFunction(update_status_callback);

 Plymouth.SetUpdateStatusFunction(scroll_message_callback);


#----------------------------------------- Quit --------------------------------

fun quit_callback ()
{
 anim.sprite.SetOpacity (1);
  if (Plymouth.GetMode() == "shutdown") {
   motif.sprite.SetOpacity(1);
  }
}

Plymouth.SetQuitFunction(quit_callback);

Zasadniczo skrypt można zastosować do dowolnego motywu, wystarczy podać nazwy plików obrazów w folderze. I zmieniając kilka innych linii, aby dostosować obrazy na ekranie. Albo to, co robisz, to kopiowanie niezbędnej części, np. Powiedzmy, że chcesz część postępu, więc wszystko, co musisz zrobić, to skopiować wszystko z

----------------------------------------- Pasek postępu ------- -------------------------

do

----------------------------------------- Aktualizacja statusu ------- -------------------------

Po zakończeniu edycji skryptu mdv.script upewnij się, że sudo update-initramfs -u przy następnym uruchomieniu zobaczysz nowy splash.

Zapoznaj się z linkami podanymi w moim pytaniu, które są bardzo pouczające i pozwolą Ci zrozumieć skrypty Plymouth w krótkim czasie.

Teraz, jeśli zrobiłeś wszystko, co powiedziałem tutaj, powinieneś uruchomić przewijanie wiadomości. Teraz, jeśli chodzi o część obciętą, pracuję nad tym, ale to trochę denerwujące, że muszę ponownie uruchamiać maszynę za każdym razem, gdy wprowadzam jakieś zmiany. Czy to możliwe, aby przetestować proces uruchamiania podczas am zalogowany jak

sudo plymouthd ; sudo plymouth --show-splash ; sudo plymouth update --status="Hello" ; sleep 2 ; sudo plymouth update --status="This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. " ; sleep 10 ; sudo killall plymouthd

Innym sposobem na przetestowanie Plymouth jest skopiowanie powyższego polecenia do pliku tekstowego i dodanie, sudo plymouth update --status="your message" aby przewijać więcej wiadomości. Następnie uczyń plik wykonywalnym i uruchom w terminalu.

Mam nadzieję, że pomoże to wszystkim, którzy chcą edytować swój plymouth. Powodzenia!!!

Witalij
źródło
0

wiem, że to stary wątek, ale myślę, że znam odpowiedź na temat obcięcia tekstu, czy nie. W moim skrypcie themename.script (nie w pliku themename.plymouth) używam dwóch zmiennych.

1. NUM_SCROLL_LINES
2. LINE_WIDTH

za pomocą tych zmiennych mogę ustawić, ile linii będzie wyświetlanych i jak długo będą wyświetlane linie. Skrypt ma również funkcję, która przycina linie, jeśli mają być wyświetlane zbyt długo.

Mam nadzieję, że to będzie komuś pomocne.

Mój problem w opensuse 42.1 Leap is. plymouth nie pokazuje komunikatów rozruchowych, jakby były zapisane w /var/log/boot.log. Pokazuje systemowe wezwania do świadczenia usług.

W ten sposób edytowałem również / lib / lsb / init-functions

if [ -x /usr/bin/plymouth ]; then
  /usr/bin/plymouth update --status="$@"
fi

albo to

[ -x /usr/bin/plymouth ] && /usr/bin/plymouth update --status="$@"

Nic mi nie działało. Czy ktoś ma pomysł?

Oto istnienie skryptu themename.script, którego używam

NUM_SCROLL_LINES=52;
LINE_WIDTH=120;

wallpaper_image = Image("background.png");
screen_width = Window.GetWidth();
screen_height = Window.GetHeight();
resized_wallpaper_image = wallpaper_image.Scale(screen_width,screen_height);
wallpaper_sprite = Sprite(resized_wallpaper_image);
wallpaper_sprite.SetZ(-100);

// Initialising text images and their positions
// 20 is the height (including line spacing) of each line
for (i=0; i < NUM_SCROLL_LINES; i++) {
  lines[i]= Image.Text("", 0, 0, 0);
  message_sprite[i] = Sprite();
#  here you can set the hights and width of textdisplay. 0.005 uses almost the whole screen.
#  message_sprite[i].SetPosition(screen_width * 0.2, (screen_height * 0.6) + (i * 20), 10000);
  message_sprite[i].SetPosition(screen_width * 0.005, (screen_height * 0.005) + (i * 20), 10000);
}

// From ubuntu-logo
fun StringLength(string) {
  index = 0;
  str = String(string);
  while(str.CharAt(index)) index++;
    return index;
}

fun scroll_message_callback(text) {
  // Truncate the message if too long
  if (StringLength(text) > LINE_WIDTH) {
    text = text.SubString(0, LINE_WIDTH - 3);
    text += "...";
  }

  // Shift message one up
  for (i = 0; i < NUM_SCROLL_LINES - 1; i++) {
    lines[i] = lines[i+1];
  }

  // Create the image for the latest message
  # z.B. turquoise coloured text / (text, 0.28, 0.82, 0.80); // 1.0 = 100% 0.28 = 28% usw.
  lines[i] = Image.Text(text, 0.28, 0.82, 0.80);

  // Re-positioning the text images
  for (i = 0; i < NUM_SCROLL_LINES; i++) {
    message_sprite[i].SetImage(lines[i]);
  }

}

Plymouth.SetUpdateStatusFunction(scroll_message_callback);
użytkownik572252
źródło