1 // SPDX-License-Identifier: GPL-2.0+
3 * Implementation of a expo, a collection of scenes providing menu options
5 * Copyright 2022 Google LLC
9 #define LOG_CATEGORY LOGC_EXPO
15 #include "scene_internal.h"
17 int expo_new(const char *name, void *priv, struct expo **expp)
21 exp = calloc(1, sizeof(struct expo));
23 return log_msg_ret("expo", -ENOMEM);
24 exp->name = strdup(name);
27 return log_msg_ret("name", -ENOMEM);
30 INIT_LIST_HEAD(&exp->scene_head);
31 INIT_LIST_HEAD(&exp->str_head);
32 exp->next_id = EXPOID_BASE_ID;
39 static void estr_destroy(struct expo_string *estr)
44 void expo_destroy(struct expo *exp)
46 struct scene *scn, *next;
47 struct expo_string *estr, *enext;
49 list_for_each_entry_safe(scn, next, &exp->scene_head, sibling)
52 list_for_each_entry_safe(estr, enext, &exp->str_head, sibling)
59 uint resolve_id(struct expo *exp, uint id)
61 log_debug("resolve id %d\n", id);
64 else if (id >= exp->next_id)
65 exp->next_id = id + 1;
70 void expo_set_dynamic_start(struct expo *exp, uint dyn_start)
72 exp->next_id = dyn_start;
75 int expo_str(struct expo *exp, const char *name, uint id, const char *str)
77 struct expo_string *estr;
79 estr = calloc(1, sizeof(struct expo_string));
81 return log_msg_ret("obj", -ENOMEM);
83 estr->id = resolve_id(exp, id);
85 list_add_tail(&estr->sibling, &exp->str_head);
90 const char *expo_get_str(struct expo *exp, uint id)
92 struct expo_string *estr;
94 list_for_each_entry(estr, &exp->str_head, sibling) {
102 int expo_set_display(struct expo *exp, struct udevice *dev)
104 struct udevice *cons;
107 ret = device_find_first_child_by_uclass(dev, UCLASS_VIDEO_CONSOLE,
110 return log_msg_ret("con", ret);
118 int expo_calc_dims(struct expo *exp)
124 return log_msg_ret("dim", -ENOTSUPP);
126 list_for_each_entry(scn, &exp->scene_head, sibling) {
128 * Do the menus last so that all the menus' text objects
131 ret = scene_calc_dims(scn, false);
133 return log_msg_ret("scn", ret);
134 ret = scene_calc_dims(scn, true);
136 return log_msg_ret("scn", ret);
142 void expo_set_text_mode(struct expo *exp, bool text_mode)
144 exp->text_mode = text_mode;
147 struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id)
151 list_for_each_entry(scn, &exp->scene_head, sibling) {
152 if (scn->id == scene_id)
159 int expo_set_scene_id(struct expo *exp, uint scene_id)
164 scn = expo_lookup_scene_id(exp, scene_id);
166 return log_msg_ret("id", -ENOENT);
167 ret = scene_arrange(scn);
169 return log_msg_ret("arr", ret);
171 exp->scene_id = scene_id;
176 int expo_first_scene_id(struct expo *exp)
180 if (list_empty(&exp->scene_head))
183 scn = list_first_entry(&exp->scene_head, struct scene, sibling);
188 int expo_render(struct expo *exp)
190 struct udevice *dev = exp->display;
191 struct video_priv *vid_priv = dev_get_uclass_priv(dev);
192 struct scene *scn = NULL;
193 enum colour_idx back;
197 back = CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK) ? VID_BLACK : VID_WHITE;
198 colour = video_index_to_colour(vid_priv, back);
199 ret = video_fill(dev, colour);
201 return log_msg_ret("fill", ret);
204 scn = expo_lookup_scene_id(exp, exp->scene_id);
206 return log_msg_ret("scn", -ENOENT);
208 ret = scene_render(scn);
210 return log_msg_ret("ren", ret);
213 video_sync(dev, true);
215 return scn ? 0 : -ECHILD;
218 int expo_send_key(struct expo *exp, int key)
220 struct scene *scn = NULL;
225 scn = expo_lookup_scene_id(exp, exp->scene_id);
227 return log_msg_ret("scn", -ENOENT);
229 ret = scene_send_key(scn, key, &exp->action);
231 return log_msg_ret("key", ret);
233 /* arrange it to get any changes */
234 ret = scene_arrange(scn);
236 return log_msg_ret("arr", ret);
239 return scn ? 0 : -ECHILD;
242 int expo_action_get(struct expo *exp, struct expo_action *act)
245 exp->action.type = EXPOACT_NONE;
247 return act->type == EXPOACT_NONE ? -EAGAIN : 0;
250 int expo_apply_theme(struct expo *exp, ofnode node)
253 struct expo_theme *theme = &exp->theme;
256 log_debug("Applying theme %s\n", ofnode_get_name(node));
258 memset(theme, '\0', sizeof(struct expo_theme));
259 ofnode_read_u32(node, "font-size", &theme->font_size);
260 ofnode_read_u32(node, "menu-inset", &theme->menu_inset);
261 ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y);
262 ofnode_read_u32(node, "menu-title-margin-x",
263 &theme->menu_title_margin_x);
265 list_for_each_entry(scn, &exp->scene_head, sibling) {
266 ret = scene_apply_theme(scn, theme);
268 return log_msg_ret("app", ret);
274 int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
280 list_for_each_entry(scn, &exp->scene_head, sibling) {
281 ret = scene_iter_objs(scn, iter, priv);
283 return log_msg_ret("wr", ret);