blob: 0f44b17be69b1087dd9d7a270dc7edec07ea9620 [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;
David Sodmanbbcb0522014-09-19 10:34:07 -0700128 int64_t last_show_ms;
129 int64_t now_ms;
130 int64_t sleep_ms;
131 struct timespec sleep_spec;
David Sodman8ef20062015-01-06 09:23:40 -0800132 image_t* image;
133 uint32_t duration;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700134 int32_t c, loop_start, loop_count;
David Sodmanbbcb0522014-09-19 10:34:07 -0700135
David Sodmanbbcb0522014-09-19 10:34:07 -0700136 /*
137 * First draw the actual splash screen
138 */
David Sodmanf0a925a2015-05-04 11:19:19 -0700139 splash_clear_screen(splash);
140 term_activate(splash->terminal);
141 last_show_ms = -1;
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700142 loop_count = (splash->loop_start >= 0 && splash->loop_start < splash->num_images) ? splash->loop_count : 1;
143 loop_start = (splash->loop_start >= 0 && splash->loop_start < splash->num_images) ? splash->loop_start : 0;
144
145 for (c = 0; ((loop_count < 0) ? true : (c < loop_count)); c++)
146 for (i = (c > 0) ? loop_start : 0; i < splash->num_images; i++) {
David Sodmanf0a925a2015-05-04 11:19:19 -0700147 image = splash->image_frames[i].image;
148 status = image_load_image_from_file(image);
149 if (status != 0) {
Dominik Behr46755a42016-04-21 18:08:33 -0700150 LOG(WARNING, "image_load_image_from_file %s failed: %d:%s.",
151 image_get_filename(image), status, strerror(status));
David Sodmanf0a925a2015-05-04 11:19:19 -0700152 break;
David Sodman8ef20062015-01-06 09:23:40 -0800153 }
154
David Sodmanf0a925a2015-05-04 11:19:19 -0700155 now_ms = get_monotonic_time_ms();
156 if (last_show_ms > 0) {
157 if (splash->loop_start >= 0 && i >= splash->loop_start)
158 duration = splash->loop_duration;
159 else
160 duration = splash->image_frames[i].duration;
161 sleep_ms = duration - (now_ms - last_show_ms);
162 if (sleep_ms > 0) {
163 sleep_spec.tv_sec = sleep_ms / MS_PER_SEC;
164 sleep_spec.tv_nsec = (sleep_ms % MS_PER_SEC) * NS_PER_MS;
165 nanosleep(&sleep_spec, NULL);
166 }
167 }
168
169 now_ms = get_monotonic_time_ms();
170
171 if (i >= splash->loop_start) {
172 image_set_offset(image,
173 splash->loop_offset_x,
174 splash->loop_offset_y);
175 }
176
177 status = term_show_image(splash->terminal, image);
178 if (status != 0) {
Dominik Behr46755a42016-04-21 18:08:33 -0700179 LOG(WARNING, "term_show_image failed: %d:%s.", status, strerror(status));
David Sodmanf0a925a2015-05-04 11:19:19 -0700180 break;
181 }
Dominik Behr44e07e62016-01-13 19:43:57 -0800182 status = main_process_events(1);
David Sodmanf0a925a2015-05-04 11:19:19 -0700183 if (status != 0) {
Dominik Behr46755a42016-04-21 18:08:33 -0700184 LOG(WARNING, "input_process failed: %d:%s.", status, strerror(status));
David Sodmanf0a925a2015-05-04 11:19:19 -0700185 break;
186 }
187 last_show_ms = now_ms;
188
David Sodmanf0a925a2015-05-04 11:19:19 -0700189 image_release(image);
Dominik Behr46c567f2016-03-08 15:11:48 -0800190 /* see if we can initialize DBUS */
191 if (!dbus_is_initialized())
192 dbus_init();
David Sodmanf0a925a2015-05-04 11:19:19 -0700193 }
194
195 for (i = 0; i < splash->num_images; i++) {
196 image_destroy(splash->image_frames[i].image);
197 }
198
Dominik Behr4defb362016-01-13 12:36:14 -0800199 term_set_current_to(NULL);
David Sodmanf0a925a2015-05-04 11:19:19 -0700200
David Sodmanbbcb0522014-09-19 10:34:07 -0700201 return status;
202}
203
David Sodman8ef20062015-01-06 09:23:40 -0800204void splash_set_offset(splash_t* splash, int32_t x, int32_t y)
205{
206 if (splash) {
207 splash->offset_x = x;
208 splash->offset_y = y;
209 }
210}
211
Stéphane Marchesin00ff1872015-12-14 13:40:09 -0800212int splash_num_images(splash_t* splash)
David Sodman8ef20062015-01-06 09:23:40 -0800213{
214 if (splash)
215 return splash->num_images;
216
217 return 0;
218}
219
Dominik Behrfd9fdda2016-03-28 17:16:45 -0700220void splash_set_loop_count(splash_t* splash, int32_t count)
221{
222 if (splash)
223 splash->loop_count = count;
224}
225
David Sodman8ef20062015-01-06 09:23:40 -0800226void splash_set_default_duration(splash_t* splash, uint32_t duration)
227{
228 if (splash)
229 splash->default_duration = duration;
230}
231
232void splash_set_loop_start(splash_t* splash, int32_t loop_start)
233{
234 if (splash)
235 splash->loop_start = loop_start;
236}
237
238void splash_set_loop_duration(splash_t* splash, uint32_t duration)
239{
240 if (splash)
241 splash->loop_duration = duration;
242}
243
244void splash_set_loop_offset(splash_t* splash, int32_t x, int32_t y)
245{
246 if (splash) {
247 splash->loop_offset_x = x;
248 splash->loop_offset_y = y;
249 }
David Sodmanbbcb0522014-09-19 10:34:07 -0700250}
David Sodmanf0a925a2015-05-04 11:19:19 -0700251
Dominik Behr92d9e312016-05-04 20:10:48 -0700252void splash_set_scale(splash_t* splash, uint32_t scale)
253{
254 if (scale > MAX_SCALE_FACTOR)
255 scale = MAX_SCALE_FACTOR;
256 if (splash)
257 splash->scale = scale;
258}
259
David Sodmanf0a925a2015-05-04 11:19:19 -0700260void splash_present_term_file(splash_t* splash)
261{
262 fprintf(stdout, "%s\n", term_get_ptsname(splash->terminal));
263}
Dominik Behr32a7c892015-10-09 15:47:53 -0700264
265int splash_is_hires(splash_t* splash)
266{
Dominik Behr83010f82016-03-18 18:43:08 -0700267 if (splash && splash->terminal && term_getfb(splash->terminal))
Dominik Behr92d9e312016-05-04 20:10:48 -0700268 return fb_getwidth(term_getfb(splash->terminal)) > HIRES_THRESHOLD_HR;
Dominik Behr32a7c892015-10-09 15:47:53 -0700269 return 0;
270}
Dominik Behrb1abcba2016-04-14 14:57:21 -0700271
272void splash_redrm(splash_t* splash)
273{
274 term_redrm(splash->terminal);
275}