]>
Commit | Line | Data |
---|---|---|
76a2e17c RS |
1 | /* ply-boot-splash.h - APIs for putting up a splash screen |
2 | * | |
3 | * Copyright (C) 2007 Red Hat, Inc. | |
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: Ray Strode <rstrode@redhat.com> | |
bbd9b2f5 | 21 | * Soeren Sandmann <sandmann@redhat.com> |
76a2e17c | 22 | */ |
76a2e17c RS |
23 | #include "ply-boot-splash.h" |
24 | ||
25 | #include <assert.h> | |
26 | #include <errno.h> | |
27 | #include <stdint.h> | |
28 | #include <stdio.h> | |
29 | #include <stdlib.h> | |
30 | #include <sys/socket.h> | |
31 | #include <sys/types.h> | |
32 | #include <unistd.h> | |
fa8d0c2a | 33 | #include <wchar.h> |
76a2e17c RS |
34 | |
35 | #include "ply-boot-splash-plugin.h" | |
b753e742 | 36 | #include "ply-terminal.h" |
76a2e17c RS |
37 | #include "ply-event-loop.h" |
38 | #include "ply-list.h" | |
39 | #include "ply-logger.h" | |
2bb73dcf | 40 | #include "ply-trigger.h" |
76a2e17c | 41 | #include "ply-utils.h" |
2d7f68e4 | 42 | #include "ply-progress.h" |
6c6ecf5e | 43 | #include "ply-keyboard.h" |
6acf834f | 44 | #include "ply-key-file.h" |
76a2e17c | 45 | |
2f277ad6 RS |
46 | #ifndef UPDATES_PER_SECOND |
47 | #define UPDATES_PER_SECOND 30 | |
48 | #endif | |
49 | ||
5e33469e RS |
50 | #ifndef FRAMES_PER_SECOND |
51 | #define FRAMES_PER_SECOND 60 | |
52 | #endif | |
53 | ||
76a2e17c RS |
54 | struct _ply_boot_splash |
55 | { | |
85704145 RS |
56 | ply_event_loop_t *loop; |
57 | ply_module_handle_t *module_handle; | |
58 | const ply_boot_splash_plugin_interface_t *plugin_interface; | |
59 | ply_boot_splash_plugin_t *plugin; | |
60 | ply_boot_splash_mode_t mode; | |
61 | ply_buffer_t *boot_buffer; | |
62 | ply_trigger_t *idle_trigger; | |
c0ee9474 RS |
63 | |
64 | ply_keyboard_t *keyboard; | |
65 | ply_list_t *pixel_displays; | |
66 | ply_list_t *text_displays; | |
85704145 RS |
67 | |
68 | char *theme_path; | |
69 | char *plugin_dir; | |
70 | char *status; | |
71 | ||
72 | ply_progress_t *progress; | |
73 | ply_boot_splash_on_idle_handler_t idle_handler; | |
74 | void *idle_handler_user_data; | |
75 | ||
76 | uint32_t is_loaded : 1; | |
5e33469e | 77 | uint32_t is_shown : 1; |
85704145 | 78 | uint32_t should_force_text_mode : 1; |
76a2e17c RS |
79 | }; |
80 | ||
81 | typedef const ply_boot_splash_plugin_interface_t * | |
85704145 | 82 | (*get_plugin_interface_function_t) (void); |
76a2e17c | 83 | |
3df0f126 RS |
84 | static void ply_boot_splash_update_progress (ply_boot_splash_t *splash); |
85 | static void ply_boot_splash_detach_from_event_loop (ply_boot_splash_t *splash); | |
86 | ||
76a2e17c | 87 | ply_boot_splash_t * |
85704145 RS |
88 | ply_boot_splash_new (const char *theme_path, |
89 | const char *plugin_dir, | |
90 | ply_buffer_t *boot_buffer) | |
76a2e17c | 91 | { |
85704145 | 92 | ply_boot_splash_t *splash; |
76a2e17c | 93 | |
85704145 | 94 | assert (theme_path != NULL); |
76a2e17c | 95 | |
85704145 RS |
96 | splash = calloc (1, sizeof(ply_boot_splash_t)); |
97 | splash->loop = NULL; | |
98 | splash->theme_path = strdup (theme_path); | |
99 | splash->plugin_dir = strdup (plugin_dir); | |
100 | splash->module_handle = NULL; | |
101 | splash->mode = PLY_BOOT_SPLASH_MODE_INVALID; | |
76a2e17c | 102 | |
85704145 | 103 | splash->boot_buffer = boot_buffer; |
c0ee9474 RS |
104 | splash->pixel_displays = ply_list_new (); |
105 | splash->text_displays = ply_list_new (); | |
fa8d0c2a | 106 | |
85704145 | 107 | return splash; |
76a2e17c RS |
108 | } |
109 | ||
c0ee9474 RS |
110 | void |
111 | ply_boot_splash_set_keyboard (ply_boot_splash_t *splash, | |
112 | ply_keyboard_t *keyboard) | |
24a21ee0 | 113 | { |
c0ee9474 RS |
114 | if (splash->plugin_interface->set_keyboard == NULL) |
115 | return; | |
24a21ee0 | 116 | |
c0ee9474 RS |
117 | splash->plugin_interface->set_keyboard (splash->plugin, keyboard); |
118 | splash->keyboard = keyboard; | |
24a21ee0 RS |
119 | } |
120 | ||
c0ee9474 RS |
121 | void |
122 | ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash) | |
24a21ee0 | 123 | { |
c0ee9474 RS |
124 | if (splash->plugin_interface->unset_keyboard == NULL) |
125 | return; | |
24a21ee0 | 126 | |
c0ee9474 RS |
127 | splash->plugin_interface->unset_keyboard (splash->plugin, splash->keyboard); |
128 | } | |
24a21ee0 | 129 | |
c0ee9474 RS |
130 | void |
131 | ply_boot_splash_add_pixel_display (ply_boot_splash_t *splash, | |
132 | ply_pixel_display_t *display) | |
133 | { | |
134 | unsigned long width, height; | |
24a21ee0 | 135 | |
c0ee9474 RS |
136 | if (splash->plugin_interface->add_pixel_display == NULL) |
137 | return; | |
24a21ee0 | 138 | |
c0ee9474 RS |
139 | width = ply_pixel_display_get_width (display); |
140 | height = ply_pixel_display_get_height (display); | |
24a21ee0 | 141 | |
c0ee9474 | 142 | ply_trace ("adding %lux%lu pixel display", width, height); |
24a21ee0 | 143 | |
5e33469e RS |
144 | if (splash->is_shown) { |
145 | ply_trace ("Splash already shown, so pausing display until next frame update"); | |
146 | ply_pixel_display_pause_updates (display); | |
147 | } | |
148 | ||
c0ee9474 RS |
149 | splash->plugin_interface->add_pixel_display (splash->plugin, display); |
150 | ply_list_append_data (splash->pixel_displays, display); | |
151 | } | |
24a21ee0 | 152 | |
c0ee9474 RS |
153 | void |
154 | ply_boot_splash_remove_pixel_display (ply_boot_splash_t *splash, | |
155 | ply_pixel_display_t *display) | |
156 | { | |
157 | unsigned long width, height; | |
24a21ee0 | 158 | |
c0ee9474 RS |
159 | if (splash->plugin_interface->remove_pixel_display == NULL) |
160 | return; | |
24a21ee0 | 161 | |
c0ee9474 RS |
162 | width = ply_pixel_display_get_width (display); |
163 | height = ply_pixel_display_get_height (display); | |
24a21ee0 | 164 | |
c0ee9474 | 165 | ply_trace ("removing %lux%lu pixel display", width, height); |
24a21ee0 | 166 | |
c0ee9474 RS |
167 | splash->plugin_interface->remove_pixel_display (splash->plugin, display); |
168 | ply_list_remove_data (splash->pixel_displays, display); | |
24a21ee0 RS |
169 | } |
170 | ||
171 | void | |
c0ee9474 RS |
172 | ply_boot_splash_add_text_display (ply_boot_splash_t *splash, |
173 | ply_text_display_t *display) | |
24a21ee0 | 174 | { |
c0ee9474 | 175 | int number_of_columns, number_of_rows; |
10ac8d2d | 176 | ply_terminal_t *terminal; |
24a21ee0 | 177 | |
c0ee9474 | 178 | if (splash->plugin_interface->add_text_display == NULL) |
85704145 | 179 | return; |
24a21ee0 | 180 | |
c0ee9474 RS |
181 | number_of_columns = ply_text_display_get_number_of_columns (display); |
182 | number_of_rows = ply_text_display_get_number_of_rows (display); | |
183 | ||
184 | ply_trace ("adding %dx%d text display", number_of_columns, number_of_rows); | |
185 | ||
186 | splash->plugin_interface->add_text_display (splash->plugin, display); | |
10ac8d2d | 187 | |
188 | terminal = ply_text_display_get_terminal (display); | |
189 | if (terminal) | |
190 | ply_terminal_set_unbuffered_input (terminal); | |
191 | ||
c0ee9474 | 192 | ply_list_append_data (splash->text_displays, display); |
24a21ee0 RS |
193 | } |
194 | ||
195 | void | |
c0ee9474 RS |
196 | ply_boot_splash_remove_text_display (ply_boot_splash_t *splash, |
197 | ply_text_display_t *display) | |
24a21ee0 | 198 | { |
c0ee9474 | 199 | int number_of_columns, number_of_rows; |
24a21ee0 | 200 | |
c0ee9474 | 201 | if (splash->plugin_interface->remove_text_display == NULL) |
85704145 | 202 | return; |
24a21ee0 | 203 | |
c0ee9474 RS |
204 | number_of_columns = ply_text_display_get_number_of_columns (display); |
205 | number_of_rows = ply_text_display_get_number_of_rows (display); | |
206 | ||
207 | ply_trace ("removing %dx%d text display", number_of_columns, number_of_rows); | |
208 | ||
209 | splash->plugin_interface->remove_text_display (splash->plugin, display); | |
210 | ply_list_remove_data (splash->text_displays, display); | |
24a21ee0 RS |
211 | } |
212 | ||
dfc91615 RS |
213 | bool |
214 | ply_boot_splash_load (ply_boot_splash_t *splash) | |
76a2e17c | 215 | { |
85704145 RS |
216 | ply_key_file_t *key_file; |
217 | char *module_name; | |
218 | char *module_path; | |
6acf834f | 219 | |
85704145 | 220 | assert (splash != NULL); |
76a2e17c | 221 | |
85704145 | 222 | get_plugin_interface_function_t get_boot_splash_plugin_interface; |
76a2e17c | 223 | |
85704145 | 224 | key_file = ply_key_file_new (splash->theme_path); |
76a2e17c | 225 | |
310b63cd RS |
226 | if (!ply_key_file_load (key_file)) { |
227 | ply_key_file_free (key_file); | |
85704145 | 228 | return false; |
310b63cd | 229 | } |
76a2e17c | 230 | |
85704145 | 231 | module_name = ply_key_file_get_value (key_file, "Plymouth Theme", "ModuleName"); |
6acf834f | 232 | |
85704145 RS |
233 | asprintf (&module_path, "%s%s.so", |
234 | splash->plugin_dir, module_name); | |
235 | free (module_name); | |
6acf834f | 236 | |
85704145 | 237 | splash->module_handle = ply_open_module (module_path); |
6acf834f | 238 | |
85704145 | 239 | free (module_path); |
6acf834f | 240 | |
85704145 RS |
241 | if (splash->module_handle == NULL) { |
242 | ply_key_file_free (key_file); | |
243 | return false; | |
244 | } | |
76a2e17c | 245 | |
85704145 RS |
246 | get_boot_splash_plugin_interface = (get_plugin_interface_function_t) |
247 | ply_module_look_up_function (splash->module_handle, | |
248 | "ply_boot_splash_plugin_get_interface"); | |
249 | ||
250 | if (get_boot_splash_plugin_interface == NULL) { | |
251 | ply_save_errno (); | |
252 | ply_close_module (splash->module_handle); | |
253 | splash->module_handle = NULL; | |
254 | ply_key_file_free (key_file); | |
255 | ply_restore_errno (); | |
256 | return false; | |
257 | } | |
76a2e17c | 258 | |
85704145 | 259 | splash->plugin_interface = get_boot_splash_plugin_interface (); |
76a2e17c | 260 | |
85704145 RS |
261 | if (splash->plugin_interface == NULL) { |
262 | ply_save_errno (); | |
263 | ply_close_module (splash->module_handle); | |
264 | splash->module_handle = NULL; | |
265 | ply_key_file_free (key_file); | |
266 | ply_restore_errno (); | |
267 | return false; | |
268 | } | |
76a2e17c | 269 | |
85704145 | 270 | splash->plugin = splash->plugin_interface->create_plugin (key_file); |
6acf834f | 271 | |
85704145 | 272 | ply_key_file_free (key_file); |
76a2e17c | 273 | |
85704145 | 274 | assert (splash->plugin != NULL); |
76a2e17c | 275 | |
85704145 | 276 | splash->is_loaded = true; |
dfc91615 | 277 | |
85704145 | 278 | return true; |
76a2e17c RS |
279 | } |
280 | ||
57108e50 RS |
281 | bool |
282 | ply_boot_splash_load_built_in (ply_boot_splash_t *splash) | |
283 | { | |
85704145 | 284 | get_plugin_interface_function_t get_boot_splash_plugin_interface; |
57108e50 | 285 | |
85704145 | 286 | assert (splash != NULL); |
57108e50 | 287 | |
85704145 | 288 | splash->module_handle = ply_open_built_in_module (); |
57108e50 | 289 | |
85704145 RS |
290 | if (splash->module_handle == NULL) |
291 | return false; | |
57108e50 | 292 | |
85704145 RS |
293 | get_boot_splash_plugin_interface = (get_plugin_interface_function_t) |
294 | ply_module_look_up_function (splash->module_handle, | |
295 | "ply_boot_splash_plugin_get_interface"); | |
57108e50 | 296 | |
85704145 RS |
297 | if (get_boot_splash_plugin_interface == NULL) { |
298 | ply_save_errno (); | |
299 | ply_close_module (splash->module_handle); | |
300 | splash->module_handle = NULL; | |
301 | ply_restore_errno (); | |
302 | return false; | |
303 | } | |
57108e50 | 304 | |
85704145 | 305 | splash->plugin_interface = get_boot_splash_plugin_interface (); |
57108e50 | 306 | |
85704145 RS |
307 | if (splash->plugin_interface == NULL) { |
308 | ply_save_errno (); | |
309 | ply_close_module (splash->module_handle); | |
310 | splash->module_handle = NULL; | |
311 | ply_restore_errno (); | |
312 | return false; | |
313 | } | |
57108e50 | 314 | |
85704145 | 315 | splash->plugin = splash->plugin_interface->create_plugin (NULL); |
57108e50 | 316 | |
85704145 | 317 | assert (splash->plugin != NULL); |
57108e50 | 318 | |
85704145 | 319 | splash->is_loaded = true; |
57108e50 | 320 | |
85704145 | 321 | return true; |
57108e50 RS |
322 | } |
323 | ||
dfc91615 RS |
324 | void |
325 | ply_boot_splash_unload (ply_boot_splash_t *splash) | |
76a2e17c | 326 | { |
85704145 RS |
327 | assert (splash != NULL); |
328 | assert (splash->plugin != NULL); | |
329 | assert (splash->plugin_interface != NULL); | |
330 | assert (splash->module_handle != NULL); | |
76a2e17c | 331 | |
85704145 RS |
332 | splash->plugin_interface->destroy_plugin (splash->plugin); |
333 | splash->plugin = NULL; | |
76a2e17c | 334 | |
85704145 RS |
335 | ply_close_module (splash->module_handle); |
336 | splash->plugin_interface = NULL; | |
337 | splash->module_handle = NULL; | |
2f277ad6 | 338 | |
85704145 | 339 | splash->is_loaded = false; |
76a2e17c RS |
340 | } |
341 | ||
24a21ee0 | 342 | static void |
c0ee9474 RS |
343 | remove_pixel_displays (ply_boot_splash_t *splash) |
344 | { | |
345 | ply_list_node_t *node; | |
346 | ||
347 | if (splash->plugin_interface->remove_pixel_display == NULL) | |
348 | return; | |
349 | ||
350 | ply_trace ("removing pixel displays"); | |
351 | ||
352 | node = ply_list_get_first_node (splash->pixel_displays); | |
353 | while (node != NULL) { | |
354 | ply_pixel_display_t *display; | |
355 | ply_list_node_t *next_node; | |
356 | unsigned long width, height; | |
357 | ||
358 | display = ply_list_node_get_data (node); | |
359 | next_node = ply_list_get_next_node (splash->pixel_displays, node); | |
360 | ||
361 | width = ply_pixel_display_get_width (display); | |
362 | height = ply_pixel_display_get_height (display); | |
363 | ||
364 | ply_trace ("Removing %lux%lu pixel display", width, height); | |
365 | ||
366 | splash->plugin_interface->remove_pixel_display (splash->plugin, display); | |
367 | ||
368 | node = next_node; | |
369 | } | |
370 | } | |
371 | ||
372 | static void | |
373 | remove_text_displays (ply_boot_splash_t *splash) | |
24a21ee0 | 374 | { |
85704145 | 375 | ply_list_node_t *node; |
24a21ee0 | 376 | |
c0ee9474 RS |
377 | if (splash->plugin_interface->remove_text_display == NULL) |
378 | return; | |
379 | ||
380 | ply_trace ("removing text displays"); | |
24a21ee0 | 381 | |
c0ee9474 | 382 | node = ply_list_get_first_node (splash->text_displays); |
85704145 | 383 | while (node != NULL) { |
c0ee9474 | 384 | ply_text_display_t *display; |
85704145 | 385 | ply_list_node_t *next_node; |
c0ee9474 | 386 | int number_of_columns, number_of_rows; |
24a21ee0 | 387 | |
c0ee9474 RS |
388 | display = ply_list_node_get_data (node); |
389 | next_node = ply_list_get_next_node (splash->text_displays, node); | |
24a21ee0 | 390 | |
c0ee9474 RS |
391 | number_of_columns = ply_text_display_get_number_of_columns (display); |
392 | number_of_rows = ply_text_display_get_number_of_rows (display); | |
393 | ||
394 | ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows); | |
24a21ee0 | 395 | |
c0ee9474 | 396 | splash->plugin_interface->remove_text_display (splash->plugin, display); |
24a21ee0 | 397 | |
85704145 RS |
398 | node = next_node; |
399 | } | |
24a21ee0 RS |
400 | } |
401 | ||
8a6d13f9 RS |
402 | void |
403 | ply_boot_splash_free (ply_boot_splash_t *splash) | |
404 | { | |
85704145 RS |
405 | ply_trace ("freeing splash"); |
406 | if (splash == NULL) | |
407 | return; | |
408 | ||
409 | if (splash->loop != NULL) { | |
410 | if (splash->plugin_interface->on_boot_progress != NULL) { | |
411 | ply_event_loop_stop_watching_for_timeout (splash->loop, | |
412 | (ply_event_loop_timeout_handler_t) | |
413 | ply_boot_splash_update_progress, splash); | |
414 | } | |
415 | ||
416 | ply_event_loop_stop_watching_for_exit (splash->loop, (ply_event_loop_exit_handler_t) | |
417 | ply_boot_splash_detach_from_event_loop, | |
418 | splash); | |
3df0f126 RS |
419 | } |
420 | ||
f8068438 RS |
421 | if (splash->module_handle != NULL) { |
422 | ply_boot_splash_unset_keyboard (splash); | |
c0ee9474 | 423 | |
f8068438 RS |
424 | remove_pixel_displays (splash); |
425 | ply_list_free (splash->pixel_displays); | |
c0ee9474 | 426 | |
f8068438 RS |
427 | remove_text_displays (splash); |
428 | ply_list_free (splash->text_displays); | |
24a21ee0 | 429 | |
85704145 | 430 | ply_boot_splash_unload (splash); |
f8068438 | 431 | } |
8a6d13f9 | 432 | |
85704145 RS |
433 | if (splash->idle_trigger != NULL) |
434 | ply_trigger_free (splash->idle_trigger); | |
3df0f126 | 435 | |
85704145 RS |
436 | free (splash->theme_path); |
437 | free (splash->plugin_dir); | |
438 | free (splash); | |
8a6d13f9 RS |
439 | } |
440 | ||
2f277ad6 RS |
441 | static void |
442 | ply_boot_splash_update_progress (ply_boot_splash_t *splash) | |
443 | { | |
85704145 RS |
444 | double percentage = 0.0; |
445 | double time = 0.0; | |
446 | ||
447 | assert (splash != NULL); | |
448 | ||
449 | if (splash->progress) { | |
450 | percentage = ply_progress_get_percentage (splash->progress); | |
451 | time = ply_progress_get_time (splash->progress); | |
452 | } | |
453 | ||
454 | if (splash->plugin_interface->on_boot_progress != NULL) | |
455 | splash->plugin_interface->on_boot_progress (splash->plugin, | |
456 | time, | |
457 | percentage); | |
458 | ||
459 | ply_event_loop_watch_for_timeout (splash->loop, | |
460 | 1.0 / UPDATES_PER_SECOND, | |
461 | (ply_event_loop_timeout_handler_t) | |
462 | ply_boot_splash_update_progress, splash); | |
2f277ad6 RS |
463 | } |
464 | ||
2d7f68e4 CB |
465 | void |
466 | ply_boot_splash_attach_progress (ply_boot_splash_t *splash, | |
85704145 | 467 | ply_progress_t *progress) |
2d7f68e4 | 468 | { |
85704145 RS |
469 | assert (splash != NULL); |
470 | assert (progress != NULL); | |
471 | assert (splash->progress == NULL); | |
472 | splash->progress = progress; | |
2d7f68e4 CB |
473 | } |
474 | ||
5e33469e RS |
475 | static void |
476 | ply_boot_splash_pause_pixel_displays (ply_boot_splash_t *splash) | |
477 | { | |
478 | ply_list_node_t *node; | |
479 | ||
480 | ply_list_foreach (splash->pixel_displays, node) { | |
481 | ply_pixel_display_t *display = ply_list_node_get_data (node); | |
482 | ply_pixel_display_pause_updates (display); | |
483 | } | |
484 | } | |
485 | ||
486 | static void | |
487 | ply_boot_splash_unpause_pixel_displays (ply_boot_splash_t *splash) | |
488 | { | |
489 | ply_list_node_t *node; | |
490 | ||
491 | ply_list_foreach (splash->pixel_displays, node) { | |
492 | ply_pixel_display_t *display = ply_list_node_get_data (node); | |
493 | ply_pixel_display_unpause_updates (display); | |
494 | } | |
495 | } | |
496 | ||
497 | static void | |
498 | ply_boot_splash_flush_displays (ply_boot_splash_t *splash) | |
499 | { | |
500 | if (!splash->is_shown) | |
501 | return; | |
502 | ||
503 | ply_boot_splash_unpause_pixel_displays (splash); | |
504 | ply_boot_splash_pause_pixel_displays (splash); | |
505 | } | |
506 | ||
507 | static void | |
508 | on_new_frame (ply_boot_splash_t *splash) | |
509 | { | |
510 | if (!splash->is_shown) | |
511 | return; | |
512 | ||
513 | ply_boot_splash_flush_displays (splash); | |
514 | ||
515 | ply_event_loop_watch_for_timeout (splash->loop, | |
516 | 1.0 / FRAMES_PER_SECOND, | |
517 | (ply_event_loop_timeout_handler_t) | |
518 | on_new_frame, | |
519 | splash); | |
520 | } | |
2d7f68e4 | 521 | |
76a2e17c | 522 | bool |
85704145 | 523 | ply_boot_splash_show (ply_boot_splash_t *splash, |
8124531e | 524 | ply_boot_splash_mode_t mode) |
76a2e17c | 525 | { |
85704145 RS |
526 | assert (splash != NULL); |
527 | assert (mode != PLY_BOOT_SPLASH_MODE_INVALID); | |
528 | assert (splash->module_handle != NULL); | |
529 | assert (splash->loop != NULL); | |
530 | assert (splash->plugin_interface != NULL); | |
531 | assert (splash->plugin != NULL); | |
532 | assert (splash->plugin_interface->show_splash_screen != NULL); | |
533 | ||
534 | if (splash->mode == mode) { | |
535 | ply_trace ("already set same splash screen mode"); | |
536 | return true; | |
537 | } else if (splash->mode != PLY_BOOT_SPLASH_MODE_INVALID) { | |
538 | splash->plugin_interface->hide_splash_screen (splash->plugin, | |
539 | splash->loop); | |
a1920e8a HG |
540 | if (splash->plugin_interface->on_boot_progress != NULL) { |
541 | ply_event_loop_stop_watching_for_timeout (splash->loop, | |
542 | (ply_event_loop_timeout_handler_t) | |
543 | ply_boot_splash_update_progress, splash); | |
544 | } | |
85704145 RS |
545 | } |
546 | ||
547 | ply_trace ("showing splash screen"); | |
548 | if (!splash->plugin_interface->show_splash_screen (splash->plugin, | |
549 | splash->loop, | |
550 | splash->boot_buffer, | |
551 | mode)) { | |
552 | ply_save_errno (); | |
553 | ply_trace ("can't show splash: %m"); | |
554 | ply_restore_errno (); | |
555 | return false; | |
556 | } | |
557 | ||
5e33469e RS |
558 | if (!splash->is_shown) { |
559 | size_t number_of_displays; | |
560 | ply_trace ("(this is an initial showing)"); | |
561 | number_of_displays = ply_list_get_length (splash->pixel_displays); | |
562 | ||
563 | if (number_of_displays > 0) { | |
564 | ply_trace ("Pausing %ld already added displays", | |
565 | number_of_displays); | |
566 | ply_boot_splash_pause_pixel_displays (splash); | |
567 | } | |
568 | ||
569 | ply_event_loop_watch_for_timeout (splash->loop, | |
570 | 1.0 / FRAMES_PER_SECOND, | |
571 | (ply_event_loop_timeout_handler_t) | |
572 | on_new_frame, | |
573 | splash); | |
574 | splash->is_shown = true; | |
575 | } | |
576 | ||
85704145 RS |
577 | if (splash->plugin_interface->on_boot_progress != NULL) |
578 | ply_boot_splash_update_progress (splash); | |
579 | ||
580 | splash->mode = mode; | |
581 | return true; | |
cef67c3f RH |
582 | } |
583 | ||
584 | bool | |
585 | ply_boot_splash_system_update (ply_boot_splash_t *splash, | |
586 | int progress) | |
587 | { | |
85704145 RS |
588 | assert (splash != NULL); |
589 | assert (splash->module_handle != NULL); | |
590 | assert (splash->loop != NULL); | |
591 | assert (splash->plugin_interface != NULL); | |
592 | assert (splash->plugin != NULL); | |
593 | ||
594 | if (splash->plugin_interface->system_update == NULL) | |
595 | return false; | |
596 | ||
597 | ply_trace ("updating system %i%%", progress); | |
598 | splash->plugin_interface->system_update (splash->plugin, | |
599 | progress); | |
600 | return true; | |
76a2e17c RS |
601 | } |
602 | ||
603 | void | |
604 | ply_boot_splash_update_status (ply_boot_splash_t *splash, | |
48138896 | 605 | const char *status) |
76a2e17c | 606 | { |
85704145 RS |
607 | assert (splash != NULL); |
608 | assert (status != NULL); | |
609 | assert (splash->plugin_interface != NULL); | |
610 | assert (splash->plugin != NULL); | |
611 | assert (splash->plugin_interface->update_status != NULL); | |
612 | assert (splash->mode != PLY_BOOT_SPLASH_MODE_INVALID); | |
613 | ||
614 | splash->plugin_interface->update_status (splash->plugin, status); | |
76a2e17c RS |
615 | } |
616 | ||
b8781ead RS |
617 | void |
618 | ply_boot_splash_update_output (ply_boot_splash_t *splash, | |
619 | const char *output, | |
620 | size_t size) | |
621 | { | |
85704145 RS |
622 | assert (splash != NULL); |
623 | assert (output != NULL); | |
b8781ead | 624 | |
85704145 RS |
625 | if (splash->plugin_interface->on_boot_output != NULL) |
626 | splash->plugin_interface->on_boot_output (splash->plugin, output, size); | |
b8781ead RS |
627 | } |
628 | ||
3822e357 RS |
629 | void |
630 | ply_boot_splash_root_mounted (ply_boot_splash_t *splash) | |
631 | { | |
85704145 | 632 | assert (splash != NULL); |
3822e357 | 633 | |
85704145 RS |
634 | if (splash->plugin_interface->on_root_mounted != NULL) |
635 | splash->plugin_interface->on_root_mounted (splash->plugin); | |
2f277ad6 RS |
636 | } |
637 | ||
fe6a3b00 RS |
638 | static void |
639 | ply_boot_splash_detach_from_event_loop (ply_boot_splash_t *splash) | |
640 | { | |
85704145 RS |
641 | assert (splash != NULL); |
642 | splash->loop = NULL; | |
fe6a3b00 RS |
643 | } |
644 | ||
76a2e17c RS |
645 | void |
646 | ply_boot_splash_hide (ply_boot_splash_t *splash) | |
647 | { | |
85704145 RS |
648 | assert (splash != NULL); |
649 | assert (splash->plugin_interface != NULL); | |
650 | assert (splash->plugin != NULL); | |
651 | assert (splash->plugin_interface->hide_splash_screen != NULL); | |
652 | ||
653 | splash->plugin_interface->hide_splash_screen (splash->plugin, | |
654 | splash->loop); | |
655 | ||
656 | splash->mode = PLY_BOOT_SPLASH_MODE_INVALID; | |
657 | ||
658 | if (splash->loop != NULL) { | |
5e33469e RS |
659 | if (splash->is_shown) { |
660 | ply_boot_splash_unpause_pixel_displays (splash); | |
661 | ||
662 | ply_event_loop_stop_watching_for_timeout (splash->loop, | |
663 | (ply_event_loop_timeout_handler_t) | |
664 | on_new_frame, splash); | |
665 | splash->is_shown = false; | |
666 | } | |
667 | ||
85704145 RS |
668 | if (splash->plugin_interface->on_boot_progress != NULL) { |
669 | ply_event_loop_stop_watching_for_timeout (splash->loop, | |
670 | (ply_event_loop_timeout_handler_t) | |
671 | ply_boot_splash_update_progress, splash); | |
672 | } | |
673 | ||
674 | ply_event_loop_stop_watching_for_exit (splash->loop, (ply_event_loop_exit_handler_t) | |
675 | ply_boot_splash_detach_from_event_loop, | |
676 | splash); | |
2f277ad6 | 677 | } |
76a2e17c RS |
678 | } |
679 | ||
85704145 RS |
680 | void ply_boot_splash_display_message (ply_boot_splash_t *splash, |
681 | const char *message) | |
b65d7dcf | 682 | { |
85704145 RS |
683 | assert (splash != NULL); |
684 | assert (splash->plugin_interface != NULL); | |
685 | assert (splash->plugin != NULL); | |
0880f04e | 686 | |
85704145 RS |
687 | if (splash->plugin_interface->display_message != NULL) |
688 | splash->plugin_interface->display_message (splash->plugin, message); | |
b65d7dcf | 689 | } |
df5d6ded | 690 | |
85704145 RS |
691 | void ply_boot_splash_hide_message (ply_boot_splash_t *splash, |
692 | const char *message) | |
eed3b65b | 693 | { |
85704145 RS |
694 | assert (splash != NULL); |
695 | assert (splash->plugin_interface != NULL); | |
696 | assert (splash->plugin != NULL); | |
697 | if (splash->plugin_interface->hide_message != NULL) | |
698 | splash->plugin_interface->hide_message (splash->plugin, message); | |
eed3b65b CB |
699 | } |
700 | ||
85704145 | 701 | void ply_boot_splash_display_normal (ply_boot_splash_t *splash) |
268292ba | 702 | { |
85704145 RS |
703 | assert (splash != NULL); |
704 | assert (splash->plugin_interface != NULL); | |
705 | assert (splash->plugin != NULL); | |
706 | if (splash->plugin_interface->display_normal != NULL) | |
707 | splash->plugin_interface->display_normal (splash->plugin); | |
268292ba | 708 | } |
df5d6ded | 709 | |
85704145 RS |
710 | void ply_boot_splash_display_password (ply_boot_splash_t *splash, |
711 | const char *prompt, | |
712 | int bullets) | |
b65d7dcf | 713 | { |
85704145 RS |
714 | assert (splash != NULL); |
715 | assert (splash->plugin_interface != NULL); | |
716 | assert (splash->plugin != NULL); | |
717 | if (splash->plugin_interface->display_password != NULL) | |
718 | splash->plugin_interface->display_password (splash->plugin, prompt, bullets); | |
b65d7dcf | 719 | } |
df5d6ded | 720 | |
85704145 RS |
721 | void ply_boot_splash_display_question (ply_boot_splash_t *splash, |
722 | const char *prompt, | |
723 | const char *entry_text) | |
b65d7dcf | 724 | { |
85704145 RS |
725 | assert (splash != NULL); |
726 | assert (splash->plugin_interface != NULL); | |
727 | assert (splash->plugin != NULL); | |
728 | if (splash->plugin_interface->display_question != NULL) | |
729 | splash->plugin_interface->display_question (splash->plugin, prompt, entry_text); | |
b65d7dcf CB |
730 | } |
731 | ||
853ec9c2 MP |
732 | void ply_boot_splash_display_prompt (ply_boot_splash_t *splash, |
733 | const char *prompt, | |
734 | const char *entry_text, | |
735 | bool is_secret) | |
736 | { | |
737 | assert (splash != NULL); | |
738 | assert (splash->plugin_interface != NULL); | |
739 | assert (splash->plugin != NULL); | |
740 | if (splash->plugin_interface->display_prompt != NULL) | |
741 | splash->plugin_interface->display_prompt (splash->plugin, prompt, entry_text, is_secret); | |
742 | } | |
743 | ||
5d1b49c6 TT |
744 | bool ply_boot_splash_validate_input (ply_boot_splash_t *splash, |
745 | const char *entry_text, | |
746 | const char *add_text) | |
747 | { | |
748 | bool input_valid = true; | |
e483f0c4 | 749 | |
5d1b49c6 TT |
750 | assert (splash != NULL); |
751 | assert (splash->plugin_interface != NULL); | |
752 | assert (splash->plugin != NULL); | |
753 | if (splash->plugin_interface->validate_input != NULL) | |
754 | input_valid = splash->plugin_interface->validate_input (splash->plugin, entry_text, add_text); | |
755 | return input_valid; | |
756 | } | |
b65d7dcf CB |
757 | |
758 | ||
76a2e17c RS |
759 | void |
760 | ply_boot_splash_attach_to_event_loop (ply_boot_splash_t *splash, | |
761 | ply_event_loop_t *loop) | |
762 | { | |
85704145 RS |
763 | assert (splash != NULL); |
764 | assert (loop != NULL); | |
765 | assert (splash->loop == NULL); | |
76a2e17c | 766 | |
85704145 | 767 | splash->loop = loop; |
76a2e17c | 768 | |
85704145 RS |
769 | ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) |
770 | ply_boot_splash_detach_from_event_loop, | |
771 | splash); | |
76a2e17c RS |
772 | } |
773 | ||
3df0f126 RS |
774 | static void |
775 | on_idle (ply_boot_splash_t *splash) | |
776 | { | |
85704145 RS |
777 | ply_trace ("splash now idle"); |
778 | ply_event_loop_watch_for_timeout (splash->loop, 0.01, | |
779 | (ply_event_loop_timeout_handler_t) | |
780 | splash->idle_handler, | |
781 | splash->idle_handler_user_data); | |
782 | splash->idle_handler = NULL; | |
783 | splash->idle_handler_user_data = NULL; | |
3df0f126 RS |
784 | } |
785 | ||
2bb73dcf | 786 | void |
85704145 RS |
787 | ply_boot_splash_become_idle (ply_boot_splash_t *splash, |
788 | ply_boot_splash_on_idle_handler_t idle_handler, | |
789 | void *user_data) | |
2bb73dcf | 790 | { |
85704145 RS |
791 | assert (splash->idle_trigger == NULL); |
792 | ||
a1920e8a HG |
793 | if (splash->plugin_interface->on_boot_progress != NULL && |
794 | splash->progress != NULL) { | |
85704145 | 795 | ply_progress_set_percentage (splash->progress, 1.0); |
a1920e8a HG |
796 | splash->plugin_interface->on_boot_progress (splash->plugin, |
797 | ply_progress_get_time (splash->progress), | |
798 | 1.0); | |
85704145 RS |
799 | } |
800 | ||
801 | ply_trace ("telling splash to become idle"); | |
802 | if (splash->plugin_interface->become_idle == NULL) { | |
803 | ply_event_loop_watch_for_timeout (splash->loop, 0.01, | |
804 | (ply_event_loop_timeout_handler_t) | |
805 | idle_handler, | |
806 | user_data); | |
807 | ||
808 | return; | |
809 | } | |
810 | ||
811 | splash->idle_handler = idle_handler; | |
812 | splash->idle_handler_user_data = user_data; | |
813 | ||
814 | splash->idle_trigger = ply_trigger_new (&splash->idle_trigger); | |
815 | ply_trigger_add_handler (splash->idle_trigger, | |
816 | (ply_trigger_handler_t) on_idle, | |
817 | splash); | |
818 | ||
819 | splash->plugin_interface->become_idle (splash->plugin, splash->idle_trigger); | |
2bb73dcf RS |
820 | } |
821 | ||
447c7830 HG |
822 | bool |
823 | ply_boot_splash_uses_pixel_displays (ply_boot_splash_t *splash) | |
824 | { | |
825 | return splash->plugin_interface->add_pixel_display != NULL; | |
826 | } | |
827 |