[libbluray-devel] Button effects and animated buttons
hpi1
git at videolan.org
Tue Jul 16 13:11:15 CEST 2013
libbluray | branch: master | hpi1 <hpi1 at anonymous.org> | Tue Jul 16 14:08:13 2013 +0300| [427d694f82e2f356cd51a4b13cb31f182286d8db] | committer: hpi1
Button effects and animated buttons
> http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=427d694f82e2f356cd51a4b13cb31f182286d8db
---
src/libbluray/decoders/graphics_controller.c | 101 ++++++++++++++++++++++----
1 file changed, 86 insertions(+), 15 deletions(-)
diff --git a/src/libbluray/decoders/graphics_controller.c b/src/libbluray/decoders/graphics_controller.c
index 92de18d..a8abbf6 100644
--- a/src/libbluray/decoders/graphics_controller.c
+++ b/src/libbluray/decoders/graphics_controller.c
@@ -48,6 +48,7 @@ typedef struct {
uint16_t x, y, w, h; /* button rect on overlay plane (if drawn) */
int visible_object_id; /* id of currently visible object */
int animate_indx; /* currently showing object index of animated button, < 0 for static buttons */
+ int effect_running; /* single-loop animation not yet complete */
} BOG_DATA;
struct graphics_controller_s {
@@ -79,6 +80,11 @@ struct graphics_controller_s {
BD_IG_EFFECT_SEQUENCE *out_effects;
int64_t next_effect_time; /* 90 kHz */
+ /* animated buttons */
+ unsigned frame_interval;
+ unsigned button_effect_running;
+ unsigned button_animation_running;
+
/* data */
PG_DISPLAY_SET *pgs;
PG_DISPLAY_SET *igs;
@@ -198,6 +204,7 @@ static BD_PG_OBJECT *_find_object_for_button(PG_DISPLAY_SET *s,
}
if (bog_data) {
+ bog_data->effect_running = 0;
if (bog_data->animate_indx >= 0) {
int range = object_id_end - object_id;
@@ -207,22 +214,25 @@ static BD_PG_OBJECT *_find_object_for_button(PG_DISPLAY_SET *s,
object_id += bog_data->animate_indx % (range + 1);
bog_data->animate_indx++;
- if (!repeat && bog_data->animate_indx > range) {
- /* terminate animation to the last object */
- bog_data->animate_indx = -1;
+ if (!repeat) {
+ if (bog_data->animate_indx > range) {
+ /* terminate animation to the last object */
+ bog_data->animate_indx = -1;
+ } else {
+ bog_data->effect_running = 1;
+ }
}
-
} else {
/* no animation for this button */
bog_data->animate_indx = -1;
}
+ } else {
+ if (object_id_end < 0xfffe) {
+ object_id = object_id_end;
+ }
}
}
- if (!repeat && object_id_end < 0xfffe) {
- object_id = object_id_end;
- }
-
object = _find_object(s, object_id);
return object;
@@ -393,6 +403,18 @@ static void _reset_page_state(GRAPHICS_CONTROLLER *gc)
gc->bog_data[ii].visible_object_id = -1;
}
+ /* animation frame rate */
+ static const unsigned frame_interval[8] = {
+ 0,
+ 90000 / 1001 * 24,
+ 90000 / 1000 * 24,
+ 90000 / 1000 * 25,
+ 90000 / 1001 * 30,
+ 90000 / 1000 * 50,
+ 90000 / 1001 * 60,
+ };
+ gc->frame_interval = frame_interval[s->ics->video_descriptor.frame_rate] * (page->animation_frame_rate_code + 1);
+
/* effects */
gc->effect_idx = 0;
gc->in_effects = NULL;
@@ -610,6 +632,18 @@ static void _render_rle(GRAPHICS_CONTROLLER *gc,
static void _select_button(GRAPHICS_CONTROLLER *gc, uint32_t button_id)
{
+ BD_IG_PAGE *page = NULL;
+ unsigned page_id = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID);
+ unsigned bog_idx = 0;
+
+ /* reset animation */
+ page = _find_page(&gc->igs->ics->interactive_composition, page_id);
+ if (page && _find_button_page(page, button_id, &bog_idx)) {
+ gc->bog_data[bog_idx].animate_indx = 0;
+ gc->next_effect_time = bd_get_scr();
+ }
+
+ /* select page */
bd_psr_write(gc->regs, PSR_SELECTED_BUTTON_ID, button_id);
gc->auto_action_triggered = 0;
}
@@ -1247,6 +1281,10 @@ static int _render_page(GRAPHICS_CONTROLLER *gc,
unsigned page_id = bd_psr_read(gc->regs, PSR_MENU_PAGE_ID);
unsigned ii;
unsigned selected_button_id = bd_psr_read(gc->regs, PSR_SELECTED_BUTTON_ID);
+ BD_IG_BUTTON *auto_activate_button = NULL;
+
+ gc->button_effect_running = 0;
+ gc->button_animation_running = 0;
if (s->ics->interactive_composition.ui_model == IG_UI_MODEL_POPUP && !gc->popup_visible) {
@@ -1321,12 +1359,9 @@ static int _render_page(GRAPHICS_CONTROLLER *gc,
if (button->auto_action_flag && !gc->auto_action_triggered) {
if (cmds) {
- GC_TRACE(" auto-activate #%d\n", button->id);
-
- cmds->num_nav_cmds = button->num_nav_cmds;
- cmds->nav_cmds = button->nav_cmds;
-
- gc->auto_action_triggered = 1;
+ if (!auto_activate_button) {
+ auto_activate_button = button;
+ }
} else {
GC_ERROR(" auto-activate #%d not triggered (!cmds)\n", button->id);
}
@@ -1341,6 +1376,24 @@ static int _render_page(GRAPHICS_CONTROLLER *gc,
_render_button(gc, button, palette, BTN_NORMAL, &gc->bog_data[ii]);
}
+
+ gc->button_effect_running += gc->bog_data[ii].effect_running;
+ gc->button_animation_running += (gc->bog_data[ii].animate_indx >= 0);
+ }
+
+ /* process auto-activate */
+ if (auto_activate_button) {
+ GC_TRACE(" auto-activate #%d\n", auto_activate_button->id);
+
+ /* do not trigger auto action before single-loop animations have been terminated */
+ if (gc->button_effect_running) {
+ GC_TRACE(" auto-activate #%d not triggered (ANIMATING)\n", auto_activate_button->id);
+ } else {
+ cmds->num_nav_cmds = auto_activate_button->num_nav_cmds;
+ cmds->nav_cmds = auto_activate_button->nav_cmds;
+
+ gc->auto_action_triggered = 1;
+ }
}
if (gc->ig_dirty) {
@@ -1379,6 +1432,11 @@ static int _user_input(GRAPHICS_CONTROLLER *gc, uint32_t key, GC_NAV_CMDS *cmds)
return -1;
}
+ if (gc->button_effect_running) {
+ GC_ERROR("_user_input(): button_effect_running\n");
+ return -1;
+ }
+
GC_TRACE("_user_input(%d)\n", key);
page = _find_page(&s->ics->interactive_composition, page_id);
@@ -1571,6 +1629,7 @@ static void _enable_button(GRAPHICS_CONTROLLER *gc, uint32_t button_id, unsigned
bd_psr_write(gc->regs, PSR_SELECTED_BUTTON_ID, 0x10000|button_id);
}
gc->bog_data[bog_idx].enabled_button = button_id;
+ gc->bog_data[bog_idx].animate_indx = 0;
} else {
if (gc->bog_data[bog_idx].enabled_button == button_id) {
@@ -1620,6 +1679,11 @@ static int _mouse_move(GRAPHICS_CONTROLLER *gc, uint16_t x, uint16_t y, GC_NAV_C
return -1;
}
+ if (gc->button_effect_running) {
+ GC_ERROR("_mouse_move(): button_effect_running\n");
+ return -1;
+ }
+
page = _find_page(&s->ics->interactive_composition, page_id);
if (!page) {
GC_ERROR("_mouse_move(): unknown page #%d (have %d pages)\n",
@@ -1706,6 +1770,13 @@ static int _animate(GRAPHICS_CONTROLLER *gc, GC_NAV_CMDS *cmds)
}
result = _render_page(gc, 0xffff, cmds);
}
+
+ } else {
+ int64_t pts = bd_get_scr();
+ if (pts >= (gc->next_effect_time + gc->frame_interval)) {
+ gc->next_effect_time += gc->frame_interval;
+ result = _render_page(gc, 0xffff, cmds);
+ }
}
}
@@ -1847,7 +1918,7 @@ int gc_run(GRAPHICS_CONTROLLER *gc, gc_ctrl_e ctrl, uint32_t param, GC_NAV_CMDS
if (gc->ig_drawn) {
cmds->status |= GC_STATUS_MENU_OPEN;
}
- if (gc->in_effects || gc->out_effects) {
+ if (gc->in_effects || gc->out_effects || gc->button_animation_running) {
cmds->status |= GC_STATUS_ANIMATE;
}
}
More information about the libbluray-devel
mailing list