blob: 2651782b27e6381fc9aaea180974363c3714c415 [file] [log] [blame]
David Sodmanbbcb0522014-09-19 10:34:07 -07001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
David Sodman8ef20062015-01-06 09:23:40 -08007#include <fcntl.h>
David Sodmanbbcb0522014-09-19 10:34:07 -07008#include <stdbool.h>
9#include <stddef.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/mman.h>
14#include <unistd.h>
David Sodmanbbcb0522014-09-19 10:34:07 -070015
Dominik Behr797a3832016-01-11 15:53:11 -080016#include "dbus.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070017#include "dbus_interface.h"
David Sodman8ef20062015-01-06 09:23:40 -080018#include "image.h"
David Sodmanf0a925a2015-05-04 11:19:19 -070019#include "input.h"
Dominik Behr44e07e62016-01-13 19:43:57 -080020#include "main.h"
David Sodman8ef20062015-01-06 09:23:40 -080021#include "splash.h"
David Sodmanf0a925a2015-05-04 11:19:19 -070022#include "term.h"
David Sodman8ef20062015-01-06 09:23:40 -080023#include "util.h"
David Sodmanbbcb0522014-09-19 10:34:07 -070024
25#define MAX_SPLASH_IMAGES (30)
David Sodmandd5b23e2015-02-18 21:36:38 -080026#define MAX_SPLASH_WAITTIME (8)
David Sodmanbbcb0522014-09-19 10:34:07 -070027
28typedef struct {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080029 image_t* image;
30 uint32_t duration;
David Sodman8ef20062015-01-06 09:23:40 -080031} splash_frame_t;
David Sodmanbbcb0522014-09-19 10:34:07 -070032
33struct _splash_t {
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080034 terminal_t* terminal;
35 int num_images;
36 uint32_t clear;
37 splash_frame_t image_frames[MAX_SPLASH_IMAGES];
38 bool terminated;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080039 int32_t loop_start;
Dominik Behrfd9fdda2016-03-28 17:16:45 -070040 int32_t loop_count;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080041 uint32_t loop_duration;
42 uint32_t default_duration;
43 int32_t offset_x;
44 int32_t offset_y;
45 int32_t loop_offset_x;
46 int32_t loop_offset_y;
Dominik Behr92d9e312016-05-04 20:10:48 -070047 uint32_t scale;
David Sodmanbbcb0522014-09-19 10:34:07 -070048};
49
David Sodmanbf3f2842014-11-12 08:26:58 -080050
51splash_t* splash_init()
David Sodmanbbcb0522014-09-19 10:34:07 -070052{
53 splash_t* splash;
54
55 splash = (splash_t*)calloc(1, sizeof(splash_t));
Stéphane Marchesinc236e0b2015-12-14 15:29:15 -080056 if (!splash)
David Sodmanbbcb0522014-09-19 10:34:07 -070057 return NULL;
58
Dominik Behr83010f82016-03-18 18:43:08 -070059 splash->terminal = term_create_splash_term();
David Sodman8ef20062015-01-06 09:23:40 -080060 splash->loop_start = -1;
Dominik Behrfd9fdda2016-03-28 17:16:45 -070061 splash->loop_count = -1;
David Sodman8ef20062015-01-06 09:23:40 -080062 splash->default_duration = 25;
63 splash->loop_duration = 25;
Dominik Behr92d9e312016-05-04 20:10:48 -070064 splash->scale = 1;
David Sodmanbbcb0522014-09-19 10:34:07 -070065
66 return splash;
67}
68
69int splash_destroy(splash_t* splash)
70{
David Sodmanf0a925a2015-05-04 11:19:19 -070071 if (splash->terminal) {
72 term_close(splash->terminal);
73 splash->terminal = NULL;
David Sodman8ef20062015-01-06 09:23:40 -080074 }
75 free(splash);
Stéphane Marchesinf75c8512016-01-07 16:53:21 -080076 term_destroy_splash_term();
David Sodmanbbcb0522014-09-19 10:34:07 -070077 return 0;
78}
79
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080080int splash_set_clear(splash_t* splash, uint32_t clear_color)
David Sodmanbbcb0522014-09-19 10:34:07 -070081{
82 splash->clear = clear_color;
83 return 0;
84}
85
David Sodman8ef20062015-01-06 09:23:40 -080086int splash_add_image(splash_t* splash, char* filespec)
David Sodmanbbcb0522014-09-19 10:34:07 -070087{
David Sodman8ef20062015-01-06 09:23:40 -080088 image_t* image;
89 int32_t offset_x, offset_y;
Stéphane Marchesin00ff1872015-12-14 13:40:09 -080090 char* filename;
David Sodman8ef20062015-01-06 09:23:40 -080091 uint32_t duration;
David Sodmanbbcb0522014-09-19 10:34:07 -070092 if (splash->num_images >= MAX_SPLASH_IMAGES)
93 return 1;
94
David Sodman8ef20062015-01-06 09:23:40 -080095 filename = (char*)malloc(strlen(filespec) + 1);
96 parse_filespec(filespec,
97 filename,
98 &offset_x, &offset_y, &duration,
99 splash->default_duration,
100 splash->offset_x,
101 splash->offset_y);
102
103 image = image_create();
104 image_set_filename(image, filename);
105 image_set_offset(image, offset_x, offset_y);
Dominik Behr92d9e312016-05-04 20:10:48 -0700106 if (splash->scale == 0)
107 image_set_scale(image, splash_is_hires(splash) ? 2 : 1);
108 else
109 image_set_scale(image, splash->scale);
David Sodman8ef20062015-01-06 09:23:40 -0800110 splash->image_frames[splash->num_images].image = image;
111 splash->image_frames[splash->num_images].duration = duration;
David Sodmanbbcb0522014-09-19 10:34:07 -0700112 splash->num_images++;
David Sodman8ef20062015-01-06 09:23:40 -0800113
114 free(filename);
David Sodmanbbcb0522014-09-19 10:34:07 -0700115 return 0;
116}
117
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800118static void splash_clear_screen(splash_t* splash)
David Sodmanbbcb0522014-09-19 10:34:07 -0700119{
David Sodmanf0a925a2015-05-04 11:19:19 -0700120 term_set_background(splash->terminal, splash->clear);
Dominik Behrb1abcba2016-04-14 14:57:21 -0700121 term_clear(splash->terminal);
David Sodmanbbcb0522014-09-19 10:34:07 -0700122}
123
Dominik Behr797a3832016-01-11 15:53:11 -0800124int splash_run(splash_t* splash)
David Sodmanbbcb0522014-09-19 10:34:07 -0700125{
126 int i;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700127 int status = 0;
Dominik Behr607e4dc2016-06-14 21:21:28 -0700128 /*
129 * Counters for throttling error messages. Only at most MAX_SPLASH_IMAGES
130 * of each type of error are logged so every frame of animation could log
131 * error message but it wouldn't spam the log.
132 */
133 int ec_li = 0, ec_ts = 0, ec_ip = 0;
David Sodmanbbcb0522014-09-19 10:34:07 -0700134 int64_t last_show_ms;
135 int64_t now_ms;
136 int64_t sleep_ms;
137 struct timespec sleep_spec;
David Sodman8ef20062015-01-06 09:23:40 -0800138 image_t* image;
139 uint32_t duration;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700140 int32_t c, loop_start, loop_count;
David Sodmanbbcb0522014-09-19 10:34:07 -0700141
David Sodmanbbcb0522014-09-19 10:34:07 -0700142 /*
143 * First draw the actual splash screen
144 */
David Sodmanf0a925a2015-05-04 11:19:19 -0700145 splash_clear_screen(splash);
146 term_activate(splash->terminal);
147 last_show_ms = -1;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700148 loop_count = (splash->loop_start >= 0 && splash->loop_start < splash->num_images) ? splash->loop_count : 1;
149 loop_start = (splash->loop_start >= 0 && splash->loop_start < splash->num_images) ? splash->loop_start : 0;
150
151 for (c = 0; ((loop_count < 0) ? true : (c < loop_count)); c++)
152 for (i = (c > 0) ? loop_start : 0; i < splash->num_images; i++) {
David Sodmanf0a925a2015-05-04 11:19:19 -0700153 image = splash->image_frames[i].image;
154 status = image_load_image_from_file(image);
Dominik Behr607e4dc2016-06-14 21:21:28 -0700155 if (status != 0 && ec_li < MAX_SPLASH_IMAGES) {
Dominik Behr46755a42016-04-21 18:08:33 -0700156 LOG(WARNING, "image_load_image_from_file %s failed: %d:%s.",
157 image_get_filename(image), status, strerror(status));
Dominik Behr607e4dc2016-06-14 21:21:28 -0700158 ec_li++;
David Sodman8ef20062015-01-06 09:23:40 -0800159 }
Dominik Behr607e4dc2016-06-14 21:21:28 -0700160 /*
161 * Check status again after timing code so we preserve animation
162 * frame timings and dont's monopolize CPU time.
163 */
David Sodmanf0a925a2015-05-04 11:19:19 -0700164 now_ms = get_monotonic_time_ms();
165 if (last_show_ms > 0) {
166 if (splash->loop_start >= 0 && i >= splash->loop_start)
167 duration = splash->loop_duration;
168 else
169 duration = splash->image_frames[i].duration;
170 sleep_ms = duration - (now_ms - last_show_ms);
171 if (sleep_ms > 0) {
172 sleep_spec.tv_sec = sleep_ms / MS_PER_SEC;
173 sleep_spec.tv_nsec = (sleep_ms % MS_PER_SEC) * NS_PER_MS;
174 nanosleep(&sleep_spec, NULL);
175 }
176 }
177
178 now_ms = get_monotonic_time_ms();
Dominik Behr607e4dc2016-06-14 21:21:28 -0700179 if (status != 0) {
180 goto img_error;
181 }
David Sodmanf0a925a2015-05-04 11:19:19 -0700182
183 if (i >= splash->loop_start) {
184 image_set_offset(image,
185 splash->loop_offset_x,
186 splash->loop_offset_y);
187 }
188
189 status = term_show_image(splash->terminal, image);
Dominik Behr607e4dc2016-06-14 21:21:28 -0700190 if (status != 0 && ec_ts < MAX_SPLASH_IMAGES) {
Dominik Behr46755a42016-04-21 18:08:33 -0700191 LOG(WARNING, "term_show_image failed: %d:%s.", status, strerror(status));
Dominik Behr607e4dc2016-06-14 21:21:28 -0700192 ec_ts++;
193 goto img_error;
David Sodmanf0a925a2015-05-04 11:19:19 -0700194 }
Dominik Behr44e07e62016-01-13 19:43:57 -0800195 status = main_process_events(1);
Dominik Behr607e4dc2016-06-14 21:21:28 -0700196 if (status != 0 && ec_ip < MAX_SPLASH_IMAGES) {
Dominik Behr46755a42016-04-21 18:08:33 -0700197 LOG(WARNING, "input_process failed: %d:%s.", status, strerror(status));
Dominik Behr607e4dc2016-06-14 21:21:28 -0700198 ec_ip++;
David Sodmanf0a925a2015-05-04 11:19:19 -0700199 }
Dominik Behr607e4dc2016-06-14 21:21:28 -0700200img_error:
David Sodmanf0a925a2015-05-04 11:19:19 -0700201 last_show_ms = now_ms;
202
David Sodmanf0a925a2015-05-04 11:19:19 -0700203 image_release(image);
Dominik Behr46c567f2016-03-08 15:11:48 -0800204 /* see if we can initialize DBUS */
205 if (!dbus_is_initialized())
206 dbus_init();
Dominik Behr607e4dc2016-06-14 21:21:28 -0700207 if (status != 0) {
208 break;
209 }
David Sodmanf0a925a2015-05-04 11:19:19 -0700210 }
211
212 for (i = 0; i < splash->num_images; i++) {
213 image_destroy(splash->image_frames[i].image);
214 }
215
Dominik Behr4defb362016-01-13 12:36:14 -0800216 term_set_current_to(NULL);
David Sodmanf0a925a2015-05-04 11:19:19 -0700217
David Sodmanbbcb0522014-09-19 10:34:07 -0700218 return status;
219}
220
David Sodman8ef20062015-01-06 09:23:40 -0800221void splash_set_offset(splash_t* splash, int32_t x, int32_t y)
222{
223 if (splash) {
224 splash->offset_x = x;
225 splash->offset_y = y;
226 }
227}
228
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800229int splash_num_images(splash_t* splash)
David Sodman8ef20062015-01-06 09:23:40 -0800230{
231 if (splash)
232 return splash->num_images;
233
234 return 0;
235}
236
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700237void splash_set_loop_count(splash_t* splash, int32_t count)
238{
239 if (splash)
240 splash->loop_count = count;
241}
242
David Sodman8ef20062015-01-06 09:23:40 -0800243void splash_set_default_duration(splash_t* splash, uint32_t duration)
244{
245 if (splash)
246 splash->default_duration = duration;
247}
248
249void splash_set_loop_start(splash_t* splash, int32_t loop_start)
250{
251 if (splash)
252 splash->loop_start = loop_start;
253}
254
255void splash_set_loop_duration(splash_t* splash, uint32_t duration)
256{
257 if (splash)
258 splash->loop_duration = duration;
259}
260
261void splash_set_loop_offset(splash_t* splash, int32_t x, int32_t y)
262{
263 if (splash) {
264 splash->loop_offset_x = x;
265 splash->loop_offset_y = y;
266 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700267}
David Sodmanf0a925a2015-05-04 11:19:19 -0700268
Dominik Behr92d9e312016-05-04 20:10:48 -0700269void splash_set_scale(splash_t* splash, uint32_t scale)
270{
271 if (scale > MAX_SCALE_FACTOR)
272 scale = MAX_SCALE_FACTOR;
273 if (splash)
274 splash->scale = scale;
275}
276
David Sodmanf0a925a2015-05-04 11:19:19 -0700277void splash_present_term_file(splash_t* splash)
278{
279 fprintf(stdout, "%s\n", term_get_ptsname(splash->terminal));
280}
Dominik Behr32a7c892015-10-09 15:47:53 -0700281
282int splash_is_hires(splash_t* splash)
283{
Dominik Behr83010f82016-03-18 18:43:08 -0700284 if (splash && splash->terminal && term_getfb(splash->terminal))
Dominik Behr92d9e312016-05-04 20:10:48 -0700285 return fb_getwidth(term_getfb(splash->terminal)) > HIRES_THRESHOLD_HR;
Dominik Behr32a7c892015-10-09 15:47:53 -0700286 return 0;
287}
Dominik Behrb1abcba2016-04-14 14:57:21 -0700288
289void splash_redrm(splash_t* splash)
290{
291 term_redrm(splash->terminal);
292}