Guest User

Untitled

a guest
Apr 20th, 2018
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 39.02 KB | None | 0 0
  1. # ubuntu-logo.script - boot splash plugin
  2. #
  3. # Copyright (C) 2009 Canonical Ltd.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2, or (at your option)
  8. # any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  18. # 02111-1307, USA.
  19. #
  20. # Written by: Alberto Milone <alberto.milone@canonical.com>
  21. #
  22. # Based on the example provided with the "script plugin" written by:
  23. # Charlie Brej <cbrej@cs.man.ac.uk>
  24. #
  25. # Question stuff written by: Markus Waas <mail@markuswaas.de>
  26. #
  27. #
  28.  
  29. # Set the text colour in (rgb / 256)
  30. text_colour.red = 1.0;
  31. text_colour.green = 1.0;
  32. text_colour.blue = 1.0;
  33.  
  34. # Tinted text #988592
  35. tinted_text_colour.red = 0.59;
  36. tinted_text_colour.green = 0.52;
  37. tinted_text_colour.blue = 0.57;
  38.  
  39. # Action Text - #ffffff - RGB 255 255 255
  40. action_text_colour.red = 1.0;
  41. action_text_colour.green = 1.0;
  42. action_text_colour.blue = 1.0;
  43.  
  44. # Orange - #ff4012 - RGB 255 64 18
  45. debugsprite = Sprite();
  46. debugsprite_bottom = Sprite();
  47. debugsprite_medium = Sprite();
  48.  
  49. # are we currently prompting for a password?
  50. prompt_active = 0;
  51.  
  52. # General purpose function to create text
  53. fun WriteText (text, colour) {
  54. image = Image.Text (text, colour.red, colour.green, colour.blue);
  55. return image;
  56. }
  57.  
  58. fun ImageToText (text) {
  59. image = WriteText (text, text_colour);
  60. return image;
  61. }
  62.  
  63. fun ImageToTintedText (text) {
  64. image = WriteText (text, tinted_text_colour);
  65. return image;
  66. }
  67.  
  68. fun ImageToActionText (text) {
  69. image = WriteText (text, action_text_colour);
  70. return image;
  71. }
  72.  
  73. fun Debug(text) {
  74. debugsprite.SetImage(ImageToText (text));
  75. }
  76.  
  77. fun DebugBottom(text) {
  78. debugsprite_bottom.SetImage(ImageToText (text));
  79. debugsprite_bottom.SetPosition(0, (Window.GetHeight (0) - 20), 1);
  80. }
  81.  
  82. fun DebugMedium(text) {
  83. debugsprite_medium.SetImage(ImageToText (text));
  84. debugsprite_medium.SetPosition(0, (Window.GetHeight (0) - 60), 1);
  85. }
  86.  
  87. fun TextYOffset() {
  88. local.y;
  89. local.text_height;
  90. local.min_height;
  91.  
  92. # Put the 1st line below the logo + some spacing
  93. y = logo.y + logo.height + (progress_indicator.bullet_height * 7 ); # + logo_spacing;
  94.  
  95. text_height = first_line_height * 7.5;
  96.  
  97. min_height = Window.GetHeight();
  98. if (y + text_height > min_height)
  99. y = min_height - text_height;
  100.  
  101. if (y < progress_indicator.y + progress_indicator.height)
  102. return progress_indicator.y + progress_indicator.height;
  103. return y;
  104. }
  105.  
  106. #------------------------------String functions-------------------------------
  107.  
  108. # This is the equivalent for strstr()
  109. fun StringString(string, substring) {
  110. start = 0;
  111. while (String(string).CharAt (start)) {
  112. walk = 0;
  113. while (String(substring).CharAt (walk) == String(string).CharAt (start + walk) ) {
  114. walk++;
  115. if (!String(substring).CharAt (walk)) return start;
  116. }
  117. start++;
  118. }
  119.  
  120. return NULL;
  121. }
  122.  
  123. fun StringLength (string) {
  124. index = 0;
  125. while (String(string).CharAt(index)) index++;
  126. return index;
  127. }
  128.  
  129. fun StringCopy (source, beginning, end) {
  130. local.destination = "";
  131. for (index = beginning; ( ( (end == NULL) || (index <= end) ) && (String(source).CharAt(index)) ); index++) {
  132. local.destination += String(source).CharAt(index);
  133. }
  134.  
  135. return local.destination;
  136. }
  137.  
  138. fun StringReplace (source, pattern, replacement) {
  139. local.found = StringString(source, pattern);
  140. if (local.found == NULL)
  141. return source;
  142.  
  143. local.new_string = StringCopy (source, 0, local.found - 1) +
  144. replacement +
  145. StringCopy (source, local.found + StringLength(pattern), NULL);
  146.  
  147. return local.new_string;
  148. }
  149.  
  150. # it makes sense to use it only for
  151. # numbers up to 100
  152. fun StringToInteger (str) {
  153. int = -1;
  154. for (i=0; i<=100; i++) {
  155. if (i+"" == str) {
  156. int = i;
  157. break;
  158. }
  159. }
  160. return int;
  161. }
  162.  
  163. #-----------------------------------------------------------------------------
  164. # Previous background colour
  165. # #300a24 --> 0.19, 0.04, 0.14
  166. # New background colour
  167. # #2c001e --> 0.16, 0.00, 0.12
  168. #
  169. Window.SetBackgroundTopColor (0.16, 0.00, 0.12); # Nice colour on top of the screen fading to
  170. Window.SetBackgroundBottomColor (0.16, 0.00, 0.12); # an equally nice colour on the bottom
  171.  
  172. bits_per_pixel = Window.GetBitsPerPixel ();
  173. if (bits_per_pixel == 4) {
  174. logo_filename = "ubuntu-logo16.png";
  175. progress_dot_off_filename = "progress-dot-off16.png";
  176. progress_dot_on_filename = "progress-dot-on16.png";
  177. password_field_filename = "password-field16.png";
  178. question_field_filename = "password-field16.png";
  179. } else {
  180. logo_filename = "ubuntu-logo.png";
  181. progress_dot_off_filename = "progress-dot-off.png";
  182. progress_dot_on_filename = "progress-dot-on.png";
  183. password_field_filename = "password-field.png";
  184. question_field_filename = "password-field.png";
  185. }
  186.  
  187. logo.image = Image (logo_filename);
  188. logo.sprite = Sprite ();
  189. logo.sprite.SetImage (logo.image);
  190. logo.width = logo.image.GetWidth ();
  191. logo.height = logo.image.GetHeight ();
  192. logo.x = Window.GetX () + Window.GetWidth () / 2 - logo.width / 2;
  193. logo.y = Window.GetY () + Window.GetHeight () / 2 - logo.height;
  194. logo.z = 1000;
  195. logo.sprite.SetX (logo.x);
  196. logo.sprite.SetY (logo.y);
  197. logo.sprite.SetZ (logo.z);
  198. logo.sprite.SetOpacity (1);
  199.  
  200. # Spacing below the logo - in pixels
  201. logo_spacing = logo.height * 4;
  202.  
  203. message_notification[0].image = ImageToTintedText ("");
  204. message_notification[1].image = ImageToTintedText ("");
  205. fsck_notification.image = ImageToActionText ("");
  206.  
  207. status = "normal";
  208.  
  209. progress_indicator.bullet_off = Image (progress_dot_off_filename);
  210. progress_indicator.bullet_on = Image (progress_dot_on_filename);
  211. progress_indicator.bullet_width = progress_indicator.bullet_off.GetWidth ();
  212. progress_indicator.bullet_height = progress_indicator.bullet_off.GetHeight ();
  213. progress_indicator.bullet_hspacing = progress_indicator.bullet_width * 1.1;
  214. progress_indicator.width = progress_indicator.bullet_width * 5;
  215. progress_indicator.height = progress_indicator.bullet_height;
  216. progress_indicator.y = logo.y + logo.height + (logo.height / 4);
  217. progress_indicator.x = Window.GetX () + Window.GetWidth () / 2 - progress_indicator.width / 2; # logo.x + 26;
  218.  
  219. # use a fixed string with ascending and descending stems to calibrate the
  220. # bounding box for the first message, so the messages below don't move up
  221. # and down according to *their* height.
  222. first_line_height = ImageToTintedText ("AfpqtM").GetHeight();
  223.  
  224. # if the user has a 640x480 or 800x600 display, we can't quite fit everything
  225. # (including passphrase prompts) with the target spacing, so scoot the text up
  226. # a bit if needed.
  227. top_of_the_text = TextYOffset();
  228.  
  229. #-----------------------------------------Logo functions------------------------------
  230.  
  231. # Call this when updating the screen
  232. fun draw_logo () {
  233. logo.sprite.SetX (logo.x);
  234. logo.sprite.SetY (logo.y);
  235. logo.sprite.SetZ (logo.z);
  236. logo.sprite.SetOpacity (1);
  237. }
  238.  
  239.  
  240. #-----------------------------------------Progress Indicator--------------------------
  241. fun set_progress_indicator () {
  242.  
  243.  
  244. # Here we assume that we can store half bullets on each half of the screen
  245. # together with some spacing
  246. local.x = progress_indicator.x;
  247.  
  248. for (index = 0; index <= 4; index++) {
  249. # Set the "off" bullets
  250. progress_indicator.bullets_off[index].sprite = Sprite (progress_indicator.bullet_off);
  251. progress_indicator.bullets_off[index].sprite.SetPosition (local.x, progress_indicator.y, 1000);
  252. progress_indicator.bullets_off[index].x = local.x;
  253. progress_indicator.bullets_off[index].y = progress_indicator.y;
  254. progress_indicator.bullets_off[index].sprite.SetOpacity (1);
  255.  
  256. #local.debug_medium_string = "Progress indicator " + index + ": x = " + progress_indicator.bullets_off[index].x +
  257. # ", y = " + progress_indicator.bullets_off[index].y + ", logo width = " + logo.width +
  258. # ", logo height = " + logo.height + " " + screen_width + " " + screen_height;
  259. #
  260. #(index % 2) && DebugMedium (local.debug_medium_string) || DebugBottom (local.debug_medium_string);
  261.  
  262. # Set the "on" bullets on top of the "off" bullets and make them transparent
  263. progress_indicator.bullets_on[index].sprite = Sprite (progress_indicator.bullet_on);
  264. progress_indicator.bullets_on[index].x = progress_indicator.bullets_off[index].x;
  265. progress_indicator.bullets_on[index].y = progress_indicator.bullets_off[index].y;
  266. progress_indicator.bullets_on[index].sprite.SetPosition (progress_indicator.bullets_on[index].x, progress_indicator.bullets_on[index].y, 10000);
  267.  
  268. progress_indicator.bullets_on[index].sprite.SetOpacity (0);
  269.  
  270. local.x += progress_indicator.bullet_hspacing;
  271. }
  272. #local.debug_string = "Progress indicator: x1 = " + progress_indicator.x + ", x2 = " + local.x + ", y = " + progress_indicator.y +
  273. # ", x logo = " + logo.x + ", y logo = " + logo.y + ", indicator width = " + progress_indicator.width;
  274. #Debug(progress_indicator.bullets_off[0].x);
  275. }
  276.  
  277.  
  278. # We have 2 bullets, one on top of the other:
  279. # The white one is on top of the red one and the former should
  280. # slowly fade so as to get a nice transition effect.
  281. fun switch_on_bullet (bullets_off, bullets_on, bullet_number, opacity) {
  282. local.x = bullets_on[bullet_number].x;
  283. local.y = bullets_on[bullet_number].y;
  284. local.z = bullets_on[bullet_number].z;
  285.  
  286. # Hide the bullets which are off
  287. bullets_off[bullet_number].sprite.SetOpacity (0);
  288.  
  289. # Show the bullets which are on
  290. bullets_on[bullet_number].sprite.SetPosition (local.x, local.y, local.z);
  291. bullets_on[bullet_number].sprite.SetOpacity (opacity);
  292.  
  293. # Bump the number of times we have switched on bullets
  294. global.times_bullets_switched++;
  295. }
  296.  
  297. fun switch_off_bullets () {
  298. # Debug("Switching off progress indicator");
  299.  
  300. set_progress_indicator ();
  301. global.times_bullets_switched = 0;
  302. global.on_off = 1;
  303. }
  304.  
  305. # This is something that we can call when we exit
  306. fun switch_on_bullets () {
  307. # Debug("Switching off progress indicator");
  308. if (!global.progress_indicator.bullets_on) set_progress_indicator ();
  309. local = global.progress_indicator;
  310.  
  311. for (index = 0; bullets_on[index]; index++) {
  312. switch_on_bullet (bullets_off, bullets_on, index, 1.0);
  313. }
  314. }
  315.  
  316.  
  317. # Implement in boot progress callback
  318. fun animate_progress_indicator (progress, time) {
  319. if (global.progress_time == NULL) {
  320. global.progress_time = progress; #time;
  321. switch_off_bullets ();
  322. }
  323.  
  324. # Debug ("progress = " + progress + ", time = " + time + " times switched = " + global.times_bullets_switched + " on_off " + global.on_off);
  325.  
  326. # if (global.times_bullets_switched == NULL)
  327. # global.times_bullets_switched = 5;
  328.  
  329. # if (global.on_off == NULL)
  330. # global.on_off = 0;
  331.  
  332. if ((progress - global.progress_time) >= 1.0) {
  333. global.progress_time = progress;
  334.  
  335. if (global.times_bullets_switched == 5) {
  336. # Change which bullets are switched on
  337. # and which ones are switched off
  338. global.on_off = !global.on_off;
  339. global.times_bullets_switched = 0;
  340. }
  341.  
  342. if (global.on_off) {
  343. switch_on_bullet (progress_indicator.bullets_off, progress_indicator.bullets_on,
  344. global.times_bullets_switched, 1.0);
  345. }
  346. else {
  347. switch_on_bullet (progress_indicator.bullets_on, progress_indicator.bullets_off,
  348. global.times_bullets_switched, 1.0);
  349. }
  350. }
  351.  
  352.  
  353. # Start setting bullets to "on" with translucency
  354. # for (index = 0; index <= 5; index++) {
  355. # opacity = 0.0;
  356. # while (opacity <= 1.0) {
  357. # switch_on_bullet (progress_indicator.bullets_off, progress_indicator.bullets_on,
  358. # index, opacity);
  359. # opacity += 0.1;
  360. # }
  361. # }
  362. }
  363.  
  364.  
  365. #-----------------------------------------Label utility functions---------------------
  366.  
  367. # label should be either a string or NULL
  368. # Images for n lines will be created and returned as items of the
  369. # message_label array
  370. #
  371. fun get_message_label (label, is_fake, is_action_line) {
  372. # Debug("Get Label position");
  373. local.message_label;
  374.  
  375. if (is_fake)
  376. # Create a fake label so as to get the y coordinate of
  377. # a standard-length label.
  378. local.message_image = ImageToTintedText ("This is a fake message");
  379. else
  380. local.message_image = (is_action_line) && ImageToActionText (label) || ImageToTintedText (label);
  381.  
  382. message_label.width = message_image.GetWidth ();
  383. message_label.height = message_image.GetHeight ();
  384.  
  385. # Center the line horizontally
  386. message_label.x = Window.GetX () + Window.GetWidth () / 2 - message_label.width / 2;
  387.  
  388. message_label.y = top_of_the_text;
  389.  
  390. # Put the 2nd line below the fsck line
  391. if (is_action_line) {
  392. local.fsck_label.y = message_label.y + (first_line_height + first_line_height / 2);
  393. message_label.y = local.fsck_label.y + (first_line_height * 2);
  394. }
  395.  
  396. # Debug("action label x = " + message_label.x + " y = " + message_label.y );
  397.  
  398. # message_debug = "msg_x = " + message_label.x + " msg_y = " + message_label.y +
  399. # "msg_width = " + message_label.width + " msg_height = " +
  400. # message_label.height + " message = " + label;
  401. # Debug(message_debug);
  402.  
  403. return message_label;
  404.  
  405. }
  406.  
  407. # Create an fsck label and/or get its position
  408. fun get_fsck_label (label, is_fake) {
  409. # Debug("Get Label position");
  410. local.fsck_label = global.progress_label;
  411.  
  412. if (is_fake)
  413. fsck_label.image = ImageToTintedText ("This is a fake message");
  414. else
  415. fsck_label.image = ImageToTintedText (label);
  416.  
  417. fsck_label.width = fsck_label.image.GetWidth ();
  418. fsck_label.height = fsck_label.image.GetHeight ();
  419.  
  420. # Centre the label horizontally
  421. fsck_label.x = Window.GetX () + Window.GetWidth () / 2 - fsck_label.width / 2;
  422.  
  423. local.first_label = get_message_label (label, 1, 0);
  424.  
  425. # Place the label below the 1st message line
  426. fsck_label.y = local.first_label.y + local.first_label.height + (local.first_label.height / 2);
  427.  
  428. # message_debug = "msg_x = " + fsck_label.x + " msg_y = " + fsck_label.y +
  429. # "msg_width = " + fsck_label.width + " msg_height = " +
  430. # fsck_label.height + " message = " + label;
  431. # Debug(message_debug);
  432.  
  433. return fsck_label;
  434. }
  435.  
  436. #-----------------------------------------Message stuff --------------------------------
  437. #
  438.  
  439. # Set up a message label
  440. #
  441. # NOTE: this is called when doing something like 'plymouth message "hello world"'
  442. #
  443. fun setup_message (message_text, x, y, z, index) {
  444. # Debug("Message setup");
  445. global.message_notification[index].image = (index) && ImageToActionText (message_text) || ImageToTintedText (message_text);
  446.  
  447. # Set up the text message, if any
  448. message_notification[index].x = x;
  449. message_notification[index].y = y;
  450. message_notification[index].z = z;
  451.  
  452. message_notification[index].sprite = Sprite ();
  453. message_notification[index].sprite.SetImage (message_notification[index].image);
  454. message_notification[index].sprite.SetX (message_notification[index].x);
  455. message_notification[index].sprite.SetY (message_notification[index].y);
  456. message_notification[index].sprite.SetZ (message_notification[index].z);
  457.  
  458. }
  459.  
  460. fun show_message (index) {
  461. if (global.message_notification[index].sprite) global.message_notification[index].sprite.SetOpacity(1);
  462. }
  463.  
  464. fun hide_message (index) {
  465. if (global.message_notification[index].sprite) global.message_notification[index].sprite.SetOpacity(0);
  466. }
  467.  
  468.  
  469.  
  470.  
  471. # the callback function is called when new message should be displayed.
  472. # First arg is message to display.
  473. fun message_callback (message)
  474. {
  475. # Debug("Message callback");
  476. is_fake = 0;
  477. if (!message || (message == "")) is_fake = 1;
  478.  
  479. local.substring = "keys:";
  480.  
  481. # Look for the "keys:" prefix
  482. local.keys = StringString(message, local.substring);
  483.  
  484. local.is_action_line = (keys != NULL);
  485. #Debug("keys " + local.keys + " substring length = " + StringLength(local.substring));
  486.  
  487. # Get the message without the "keys:" prefix
  488. if (keys != NULL)
  489. message = StringCopy (message, keys + StringLength(local.substring), NULL);
  490.  
  491. # Get the message without the "fsckd-cancel-msg" prefix as we don't support i18n
  492. substring = "fsckd-cancel-msg:";
  493. keys = StringString(message, substring);
  494. if (keys != NULL)
  495. message = StringCopy(message, keys + StringLength(substring), NULL);
  496.  
  497. local.label.is_fake = is_fake;
  498. label = get_message_label(message, is_fake, is_action_line);
  499. label.z = 10000;
  500.  
  501. setup_message (message, label.x, label.y, label.z, is_action_line);
  502. if (prompt_active && local.is_action_line)
  503. hide_message (is_action_line);
  504. else
  505. show_message (is_action_line);
  506.  
  507. }
  508.  
  509.  
  510. #-----------------------------------------Display Password stuff -----------------------
  511. #
  512.  
  513. fun password_dialogue_setup (message_label) {
  514. # Debug("Password dialog setup");
  515.  
  516. local.entry;
  517. local.bullet_image;
  518.  
  519. bullet_image = Image (progress_dot_off_filename);
  520. entry.image = Image (password_field_filename);
  521.  
  522. # Hide the normal labels
  523. prompt_active = 1;
  524. if (message_notification[1].sprite) hide_message (1);
  525.  
  526. # Set the prompt label
  527. label = get_message_label(message_label, 0, 1);
  528. label.z = 10000;
  529.  
  530. setup_message (message_label, label.x, label.y, label.z, 2);
  531. show_message (2);
  532.  
  533. # Set up the text entry which contains the bullets
  534. entry.sprite = Sprite ();
  535. entry.sprite.SetImage (entry.image);
  536.  
  537. # Centre the box horizontally
  538. entry.x = Window.GetX () + Window.GetWidth () / 2 - entry.image.GetWidth () / 2;
  539.  
  540. # Put the entry below the second label.
  541. entry.y = message_notification[2].y + label.height;
  542.  
  543. #Debug ("entry x = " + entry.x + ", y = " + entry.y);
  544. entry.z = 10000;
  545. entry.sprite.SetX (entry.x);
  546. entry.sprite.SetY (entry.y);
  547. entry.sprite.SetZ (entry.z);
  548.  
  549. global.password_dialogue = local;
  550. }
  551.  
  552. fun password_dialogue_opacity (opacity) {
  553. # Debug("Password dialog opacity");
  554. global.password_dialogue.opacity = opacity;
  555. local = global.password_dialogue;
  556.  
  557. # You can make the box translucent with a float
  558. # entry.sprite.SetOpacity (0.3);
  559. entry.sprite.SetOpacity (opacity);
  560. label.sprite.SetOpacity (opacity);
  561.  
  562. if (bullets) {
  563. for (index = 0; bullets[index]; index++) {
  564. bullets[index].sprite.SetOpacity (opacity);
  565. }
  566. }
  567. }
  568.  
  569.  
  570. # The callback function is called when the display should display a password dialogue.
  571. # First arg is prompt string, the second is the number of bullets.
  572. fun display_password_callback (prompt, bullets) {
  573. # Debug("Password dialog setup");
  574.  
  575. global.status = "password";
  576. if (!global.password_dialogue) password_dialogue_setup(prompt);
  577. password_dialogue_opacity (1);
  578. bullet_width = password_dialogue.bullet_image.GetWidth();
  579. bullet_y = password_dialogue.entry.y +
  580. password_dialogue.entry.image.GetHeight () / 2 -
  581. password_dialogue.bullet_image.GetHeight () / 2;
  582. margin = bullet_width;
  583. spaces = Math.Int( (password_dialogue.entry.image.GetWidth () - (margin * 2) ) / ( 2 * bullet_width / 3 ) );
  584. #Debug ("spaces = " + spaces + ", bullets = " + bullets);
  585. bullets_area.width = margin + spaces * ( 2 * bullet_width / 3);
  586. bullets_area.x = Window.GetX () + Window.GetWidth () / 2 - bullets_area.width / 2;
  587. #DebugBottom ("pwd_entry x = " + password_dialogue.entry.x + ", bullets_area.x = " + bullets_area.x + ", bullets_area.width = " + bullets_area.width);
  588. if (bullets > spaces)
  589. bullets = spaces;
  590. for (index = 0; password_dialogue.bullets[index] || index < spaces ; index++){
  591. if (!password_dialogue.bullets[index]) {
  592. password_dialogue.bullets[index].sprite = Sprite ();
  593. password_dialogue.bullets[index].sprite.SetImage (password_dialogue.bullet_image);
  594. password_dialogue.bullets[index].x = bullets_area.x + # password_dialogue.entry.x + margin +
  595. index * ( 2 * bullet_width / 3 ) ;
  596. password_dialogue.bullets[index].sprite.SetX (password_dialogue.bullets[index].x);
  597. password_dialogue.bullets[index].y = bullet_y;
  598. password_dialogue.bullets[index].sprite.SetY (password_dialogue.bullets[index].y);
  599. password_dialogue.bullets[index].z = password_dialogue.entry.z + 100 - index;
  600. password_dialogue.bullets[index].sprite.SetZ (password_dialogue.bullets[index].z);
  601. }
  602.  
  603. password_dialogue.bullets[index].sprite.SetOpacity (0);
  604.  
  605. if (index < bullets ) {
  606. password_dialogue.bullets[index].sprite.SetOpacity (1);
  607. }
  608. }
  609. }
  610.  
  611. Plymouth.SetDisplayPasswordFunction (display_password_callback);
  612.  
  613. Plymouth.SetMessageFunction (message_callback);
  614.  
  615. Plymouth.SetBootProgressFunction (animate_progress_indicator);
  616.  
  617. # Plymouth.SetBootProgressFunction: the callback function is called with two numbers, the progress (between 0 and 1) and the time spent booting so far
  618. # Plymouth.SetRootMountedFunction: the callback function is called when a new root is mounted
  619. # Plymouth.SetKeyboardInputFunction: the callback function is called with a string containing a new character entered on the keyboard
  620.  
  621. #----------------------------------------- FSCK Counter --------------------------------
  622.  
  623. # Initialise the counter
  624. fun init_fsck_count () {
  625. # The number of fsck checks in this cycle
  626. global.counter.total = 0;
  627. # The number of fsck checks already performed + the current one
  628. global.counter.current = 1;
  629. # The previous fsck
  630. global.counter.last = 0;
  631. }
  632.  
  633. # Increase the total counter
  634. fun increase_fsck_count () {
  635. global.counter.total++;
  636. }
  637.  
  638. fun increase_current_fsck_count () {
  639. global.counter.last = global.counter.current++;
  640. }
  641.  
  642. # Clear the counter
  643. fun clear_fsck_count () {
  644. global.counter = NULL;
  645. init_fsck_count ();
  646. }
  647.  
  648. #----------------------------------------- Progress Label ------------------------------
  649.  
  650.  
  651. # Change the opacity level of a progress label
  652. #
  653. # opacity = 1 -> show
  654. # opacity = 0 -> hide
  655. # opacity = 0.3 (or any other float) -> translucent
  656. #
  657. fun set_progress_label_opacity (opacity) {
  658. # the label
  659. progress_label.sprite.SetOpacity (opacity);
  660.  
  661. # Make the slot available again when hiding the bar
  662. # So that another bar can take its place
  663. if (opacity == 0) {
  664. progress_label.is_available = 1;
  665. progress_label.device = "";
  666. }
  667. }
  668.  
  669. # Set up a new Progress Bar
  670. #
  671. # TODO: Make it possible to reuse (rather than recreate) a bar
  672. # if .is_available = 1. Ideally this would just reset the
  673. # label, the associated
  674. # device and the image size of the sprite.
  675.  
  676. fun init_progress_label (device, status_string) {
  677. # Make the slot unavailable
  678. global.progress_label.is_available = 0;
  679. progress_label.progress = 0;
  680. progress_label.device = device;
  681. progress_label.status_string = status_string;
  682. }
  683.  
  684. # See if the progress label is keeping track of the fsck
  685. # of "device"
  686. #
  687. fun device_has_progress_label (device) {
  688. #DebugBottom ("label device = " + progress_label.device + " checking device " + device);
  689. return (progress_label.device == device);
  690. }
  691.  
  692. # Update the Progress bar which corresponds to index
  693. #
  694. fun update_progress_label (progress) {
  695. # If progress is NULL then we just refresh the label.
  696. # This happens when only counter.total has changed.
  697. if (progress != NULL) {
  698. progress_label.progress = progress;
  699.  
  700. #Debug("device " + progress_label.device + " progress " + progress);
  701.  
  702. # If progress >= 100% hide the label and make it available again
  703. if (progress >= 100) {
  704. set_progress_label_opacity (0);
  705.  
  706. # See if we any other fsck check is complete
  707. # and, if so, hide the progress bars and the labels
  708. on_fsck_completed ();
  709.  
  710. return 0;
  711. }
  712. }
  713. # Update progress label here
  714. #
  715. # FIXME: the queue logic from this theme should really be moved into mountall
  716. # instead of using string replacement to deal with localised strings.
  717. label = StringReplace (progress_label.status_string[0], "%1$d", global.counter.current);
  718. label = StringReplace (label, "%2$d", global.counter.total);
  719. label = StringReplace (label, "%3$d", progress_label.progress);
  720. label = StringReplace (label, "%%", "%");
  721.  
  722. progress_label = get_fsck_label (label, 0);
  723. #progress_label.progress = progress;
  724.  
  725. progress_label.sprite = Sprite (progress_label.image);
  726.  
  727. # Set up the bar
  728. progress_label.sprite.SetPosition(progress_label.x, progress_label.y, 1);
  729.  
  730. set_progress_label_opacity (1);
  731.  
  732. }
  733.  
  734. # Refresh the label so as to update counters
  735. fun refresh_progress_label () {
  736. update_progress_label (NULL);
  737. }
  738.  
  739. #----------------------------------------- FSCK Queue ----------------------------------
  740.  
  741. # Initialise the fsck queue
  742. fun init_queue () {
  743. global.fsck_queue[0].device;
  744. global.fsck_queue[0].progress;
  745. global.fsck_queue.counter = 0;
  746. global.fsck_queue.biggest_item = 0;
  747. }
  748.  
  749. fun clear_queue () {
  750. global.fsck_queue = NULL;
  751. init_queue ();
  752. }
  753.  
  754. # Return either the device index in the queue or -1
  755. fun queue_look_up_by_device (device) {
  756. for (i=0; i <= fsck_queue.biggest_item; i++) {
  757. if ((fsck_queue[i]) && (fsck_queue[i].device == device))
  758. return i;
  759. }
  760. return -1;
  761. }
  762.  
  763. # Keep track of an fsck process in the queue
  764. fun add_fsck_to_queue (device, progress) {
  765. # Look for an empty slot in the queue
  766. for (i=0; global.fsck_queue[i].device; i++) {
  767. continue;
  768. }
  769. local.index = i;
  770.  
  771. # Set device and progress
  772. global.fsck_queue[local.index].device = device;
  773. global.fsck_queue[local.index].progress = progress;
  774.  
  775. # Increase the queue counter
  776. global.fsck_queue.counter++;
  777.  
  778. # Update the max index of the array for iterations
  779. if (local.index > global.fsck_queue.biggest_item)
  780. global.fsck_queue.biggest_item = local.index;
  781.  
  782. #DebugMedium ("Adding " + device + " at " + local.index);
  783. }
  784.  
  785. fun is_queue_empty () {
  786. return (fsck_queue.counter == 0);
  787. }
  788.  
  789. fun is_progress_label_available () {
  790. return (progress_label.is_available == 1);
  791. }
  792.  
  793.  
  794. # This should cover the case in which the fsck checks in
  795. # the queue are completed before the ones showed in the
  796. # progress label
  797. fun on_queued_fsck_completed () {
  798. if (!is_queue_empty ())
  799. return;
  800.  
  801. # Hide the extra label, if any
  802. #if (progress_bar.extra_label.sprite)
  803. # progress_bar.extra_label.sprite.SetOpacity(0);
  804. }
  805.  
  806. fun remove_fsck_from_queue (index) {
  807. # Free memory which was previously allocated for
  808. # device and progress
  809. global.fsck_queue[index].device = NULL;
  810. global.fsck_queue[index].progress = NULL;
  811.  
  812. # Decrease the queue counter
  813. global.fsck_queue.counter--;
  814.  
  815. # See if there are other processes in the queue
  816. # if not, clear the extra_label
  817. on_queued_fsck_completed ();
  818. }
  819.  
  820. fun on_fsck_completed () {
  821. # We have moved on to tracking the next fsck
  822. increase_current_fsck_count ();
  823.  
  824. if (!is_progress_label_available ())
  825. return;
  826.  
  827. if (!is_queue_empty ())
  828. return;
  829.  
  830. # Hide the progress label
  831. if (progress_label.sprite)
  832. progress_label.sprite.SetOpacity (0);
  833.  
  834. # Clear the queue
  835. clear_queue ();
  836.  
  837. # Clear the fsck counter
  838. clear_fsck_count ();
  839. }
  840.  
  841. # Update an fsck process that we keep track of in the queue
  842. fun update_progress_in_queue (index, device, progress) {
  843. # If the fsck is complete, remove it from the queue
  844. if (progress >= 100) {
  845. remove_fsck_from_queue (index);
  846. on_queued_fsck_completed ();
  847. return;
  848. }
  849.  
  850. global.fsck_queue[index].device = device;
  851. global.fsck_queue[index].progress = progress;
  852.  
  853. }
  854.  
  855. # TODO: Move it to some function
  856. # Create an empty queue
  857. #init_queue ();
  858.  
  859.  
  860. #----------------------------------------- FSCK Functions ------------------------------
  861.  
  862.  
  863. # Either add a new bar for fsck checks or update an existing bar
  864. #
  865. # NOTE: no more than "progress_bar.max_number" bars are allowed
  866. #
  867. fun fsck_check (device, progress, status_string) {
  868.  
  869. # The 1st time this will take place
  870. if (!global.progress_label) {
  871. # Increase the fsck counter
  872. increase_fsck_count ();
  873.  
  874. # Set up a new label for the check
  875. init_progress_label (device, status_string);
  876. update_progress_label (progress);
  877.  
  878. return;
  879. }
  880.  
  881.  
  882. if (device_has_progress_label (device)) {
  883. # Update the progress of the existing label
  884. update_progress_label (progress);
  885. }
  886. else {
  887. # See if there's already a slot in the queue for the device
  888. local.queue_device_index = queue_look_up_by_device(device);
  889.  
  890. # See if the progress_label is available
  891. if (progress_label.is_available) {
  892.  
  893. # local.my_string = "available index " + local.available_index + " progress_bar counter is " + progress_bar.counter;
  894. # Debug(local.my_string);
  895.  
  896.  
  897. # If the fsck check for the device was in the queue, then
  898. # remove it from the queue
  899. if (local.queue_device_index >= 0) {
  900. remove_fsck_from_queue (index);
  901. }
  902. else {
  903. # Increase the fsck counter
  904. increase_fsck_count ();
  905. }
  906.  
  907. # local.my_string += local.message;
  908. #Debug("setting new label for device " + device + " progress " + progress);
  909.  
  910. # Set up a new label for the check
  911. init_progress_label (device, status_string);
  912. update_progress_label (progress);
  913.  
  914. }
  915. # If the progress_label is not available
  916. else {
  917.  
  918. # If the fsck check for the device is already in the queue
  919. # just update its progress in the queue
  920. if (local.queue_device_index >= 0) {
  921. #DebugMedium("Updating queue at " + local.queue_device_index + " for device " + device);
  922. update_progress_in_queue (local.queue_device_index, device, progress);
  923. }
  924. # Otherwise add the check to the queue
  925. else {
  926. #DebugMedium("Adding device " + device + " to queue at " + local.queue_device_index);
  927. add_fsck_to_queue (device, progress);
  928.  
  929. # Increase the fsck counter
  930. increase_fsck_count ();
  931.  
  932. refresh_progress_label ();
  933. }
  934.  
  935. }
  936. }
  937.  
  938. # if (!is_queue_empty ()) {
  939. # DebugBottom("Extra label for "+ device);
  940. #}
  941. # else {
  942. # DebugBottom("No extra label for " + device + ". 1st Device in the queue "+ fsck_queue[0].device + " counter = " + global.fsck_queue.counter);
  943. # }
  944. }
  945.  
  946.  
  947. #-----------------------------------------Update Status stuff --------------------------
  948. #
  949. # The update_status_callback is what we can use to pass plymouth whatever we want so
  950. # as to make use of features which are available only in this program (as opposed to
  951. # being available for any theme for the script plugin).
  952. #
  953. # Example:
  954. #
  955. # Thanks to the current implementation, some scripts can call "plymouth --update=fsck:sda1:40"
  956. # and this program will know that 1) we're performing and fsck check, 2) we're checking sda1,
  957. # 3) the program should set the label progress to 40%
  958. #
  959. # Other features can be easily added by parsing the string that we pass plymouth with "--update"
  960. #
  961. fun update_status_callback (status) {
  962. # Debug(status);
  963. if (!status) return;
  964.  
  965. string_it = 0;
  966. update_strings[string_it] = "";
  967.  
  968. for (i=0; (String(status).CharAt(i) != ""); i++) {
  969. local.temp_char = String(status).CharAt(i);
  970. if (temp_char != ":")
  971. update_strings[string_it] += temp_char;
  972. else
  973. update_strings[++string_it] = "";
  974. }
  975.  
  976. # my_string = update_strings[0] + " " + update_strings[1] + " " + update_strings[2];
  977. # Debug(my_string);
  978. # Let's assume that we're dealing with these strings fsck:sda1:40
  979. if ((string_it >= 2) && (update_strings[0] == "fsck")) {
  980.  
  981. device = update_strings[1];
  982. progress = update_strings[2];
  983. status_string[0] = update_strings[3]; # "Checking disk %1$d of %2$d (%3$d %% complete)"
  984. if (!status_string[0])
  985. status_string[0] = "Checking disk %1$d of %2$d (%3$d %% complete)";
  986.  
  987. if ((device != "") && (progress != "")) {
  988. progress = StringToInteger (progress);
  989.  
  990. # Make sure that the fsck_queue is initialised
  991. if (!global.fsck_queue)
  992. init_queue ();
  993.  
  994. # Make sure that the fsck counter is initialised
  995. if (!global.counter)
  996. init_fsck_count ();
  997.  
  998. # if (!global.progress_bar.extra_label.sprite)
  999. # create_extra_fsck_label ();
  1000.  
  1001. # Keep track of the fsck check
  1002. fsck_check (device, progress, status_string);
  1003. }
  1004.  
  1005. }
  1006.  
  1007. # systemd-fsckd pass fsckd:<number_devices>:<progress>:<l10n_string>
  1008. if (update_strings[0] == "fsckd") {
  1009. number_devices = StringToInteger(update_strings[1]);
  1010.  
  1011. if (number_devices > 0) {
  1012. label = update_strings[3];
  1013.  
  1014. progress_label = get_fsck_label (label, 0);
  1015. progress_label.sprite = Sprite (progress_label.image);
  1016. progress_label.sprite.SetPosition(progress_label.x, progress_label.y, 1);
  1017. progress_label.sprite.SetOpacity (1);
  1018. } else {
  1019. if (progress_label.sprite)
  1020. progress_label.sprite.SetOpacity (0);
  1021. }
  1022. }
  1023.  
  1024. }
  1025. Plymouth.SetUpdateStatusFunction (update_status_callback);
  1026.  
  1027. #-----------------------------------------Display Question stuff -----------------------
  1028.  
  1029. fun question_dialogue_setup (message_label, text_image) {
  1030. #Debug("Question dialog setup");
  1031.  
  1032. local.field;
  1033. local.content;
  1034. local.margin;
  1035.  
  1036. field.image = Image (question_field_filename);
  1037. content = Sprite ();
  1038. bullet_image = Image (progress_dot_off_filename);
  1039. margin = bullet_image.GetWidth() / 2;
  1040.  
  1041. # Hide the normal labels
  1042. prompt_active = 1;
  1043. if (message_notification[1].sprite) hide_message (1);
  1044.  
  1045. # Set the prompt label
  1046. label = get_message_label(message_label, 0, 1);
  1047. label.z = 10000;
  1048.  
  1049. setup_message (message_label, label.x, label.y, label.z, 2);
  1050. show_message (2);
  1051.  
  1052. # Set up the text field which contains the contents
  1053. field.sprite = Sprite ();
  1054. field.sprite.SetImage (field.image);
  1055.  
  1056. # Centre the box horizontally
  1057. field.x = Window.GetX () + Window.GetWidth () / 2 - field.image.GetWidth () / 2;
  1058. content_x = field.x + margin;
  1059.  
  1060. # Put the field below the second label.
  1061. field.y = message_notification[2].y + label.height;
  1062. content_y = field.y + field.image.GetHeight () / 2 - text_image.GetHeight () / 2;
  1063.  
  1064. #Debug ("field x = " + field.x + ", y = " + field.y);
  1065. field.z = 10000;
  1066. field.sprite.SetX (field.x);
  1067. field.sprite.SetY (field.y);
  1068. field.sprite.SetZ (field.z);
  1069.  
  1070. #Debug ("content_x = " + content_x + " content_y = " + content_y);
  1071. content_z = field.z + 1;
  1072. content.SetPosition (content_x, content_y, content_z);
  1073.  
  1074. global.question_dialogue = local;
  1075. }
  1076.  
  1077. # The callback function is called when the display should display a question dialogue.
  1078. # First arg is prompt string, the second is the field contents.
  1079. fun display_question_callback (prompt, contents) {
  1080. global.status = "question";
  1081. #Debug ("Reply: " + contents);
  1082.  
  1083. textImage = ImageToText(contents);
  1084. if (!global.question_dialogue) {
  1085. question_dialogue_setup(prompt, textImage);
  1086. }
  1087.  
  1088. margin = global.question_dialogue.margin;
  1089. fieldWidth = global.question_dialogue.field.image.GetWidth ();
  1090. for (i = 0; ( (textImage.GetWidth () + 2 * margin ) > fieldWidth ); i++) {
  1091. textImage = ImageToText(StringCopy (contents, i, StringLength (contents)));
  1092. }
  1093.  
  1094. global.question_dialogue.content.SetImage (textImage);
  1095. }
  1096.  
  1097.  
  1098. Plymouth.SetDisplayQuestionFunction (display_question_callback);
  1099.  
  1100. #-----------------------------------------Refresh stuff --------------------------------
  1101. #
  1102. # Calling Plymouth.SetRefreshFunction with a function will set that function to be
  1103. # called up to 50 times every second, e.g.
  1104. #
  1105. # NOTE: if a refresh function is not set, Plymouth doesn't seem to be able to update
  1106. # the screen correctly
  1107. #
  1108. fun refresh_callback ()
  1109. {
  1110. draw_logo ();
  1111. }
  1112. Plymouth.SetRefreshFunction (refresh_callback);
  1113.  
  1114.  
  1115. #-----------------------------------------Display Normal stuff -----------------------
  1116. #
  1117. # The callback function is called when the display should return to normal
  1118. fun display_normal_callback ()
  1119. {
  1120. global.status = "normal";
  1121. if (global.password_dialogue) {
  1122. password_dialogue_opacity (0);
  1123. global.password_dialogue = NULL;
  1124. if (message_notification[2].sprite) hide_message(2);
  1125. prompt_active = 0;
  1126. }
  1127. if (global.question_dialogue) {
  1128. question_dialogue_opacity (0);
  1129. global.question_dialogue = NULL;
  1130. if (message_notification[2].sprite) hide_message(2);
  1131. prompt_active = 0;
  1132. }
  1133.  
  1134. if (message_notification[1].sprite) show_message (1);
  1135.  
  1136. }
  1137.  
  1138. Plymouth.SetDisplayNormalFunction (display_normal_callback);
  1139.  
  1140.  
  1141. #----------------------------------------- Quit --------------------------------
  1142.  
  1143. # TODO: Maybe we should also hide any other dialog
  1144. # Show the logo and make the progress indicator look full when on exit
  1145. fun quit_callback ()
  1146. {
  1147. logo.sprite.SetOpacity (1);
  1148. switch_on_bullets ();
  1149. }
  1150.  
  1151. Plymouth.SetQuitFunction(quit_callback);
Add Comment
Please, Sign In to add comment