ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
video/anim/controller.c
Go to the documentation of this file.
5#include <math.h>
6#include <string.h>
7
8#include "backends.h"
9
10static bool valid_config(animation_config_t c) {
11 return c.type >= ANIMATION_SPLASH_RAINBOW && c.type <= ANIMATION_TEST_PATTERN && c.fps > 0 && c.fps <= 1000000000 &&
12 isfinite(c.speed) && c.speed >= 0 &&
14}
15
17 if (!a || !name || !valid_config(config))
18 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid animation configuration");
19 *a = (animation_t){.config = config, .visible = true};
20 NAMED_REGISTER(a, name, "animation", NULL, NULL);
21 return ASCIICHAT_OK;
22}
23
25 if (!a)
26 return;
28 memset(a, 0, sizeof(*a));
29}
30
32 if (!a)
33 return;
34 a->seconds = 0;
35 a->started = false;
36 a->last_frame = 0;
37}
38void animation_set_paused(animation_t *a, bool paused) {
39 if (a)
40 a->paused = paused;
41}
42void animation_set_visible(animation_t *a, bool visible) {
43 if (a)
44 a->visible = visible;
45}
47 if (!a || !isfinite(speed) || speed < 0)
48 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid animation speed");
49 a->config.speed = speed;
50 return ASCIICHAT_OK;
51}
52
54 if (!out || !valid_config(config) || !isfinite(seconds) || seconds < 0 || seconds * config.fps >= (double)UINT64_MAX)
55 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid animation timestamp");
56 *out = (animation_sample_t){.type = config.type,
57 .seconds = seconds,
58 .frame = (uint64_t)(seconds * config.fps),
59 .changed = true,
60 .next_frame_ns = UINT64_MAX};
61 return ASCIICHAT_OK;
62}
63
65 if (!a || !out || !valid_config(a->config) || (a->started && now < a->last_ns))
66 return SET_ERRNO(ERROR_INVALID_PARAM, "Animation timestamps must be monotonic; reset before seeking");
67 bool running =
69 double seconds = a->seconds;
70 if (a->started && running)
71 seconds += (double)(now - a->last_ns) / 1e9 * a->config.speed;
73 if (err != ASCIICHAT_OK)
74 return err;
75 out->changed = !a->started || out->frame != a->last_frame;
76 if (running) {
77 double remaining = ((double)out->frame + 1.0) / a->config.fps - seconds;
78 double delay = ceil(fmax(1.0, remaining * 1e9 / a->config.speed));
79 if (delay < (double)(UINT64_MAX - now))
80 out->next_frame_ns = now + (uint64_t)delay;
81 }
82 a->seconds = seconds;
83 a->last_ns = now;
84 a->last_frame = out->frame;
85 a->started = true;
86 return ASCIICHAT_OK;
87}
88
90 if (!s || !t || !isfinite(s->seconds) || s->seconds < 0)
91 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid animation sample or target");
92 switch (s->type) {
94 if (t->type != ANIMATION_TARGET_COLOR || !t->color.out || !isfinite(t->color.position))
95 break;
96 static const rgb_pixel_t colors[] = {{255, 0, 0}, {255, 165, 0}, {255, 255, 0}, {0, 255, 0},
97 {0, 255, 255}, {0, 0, 255}, {255, 0, 255}};
98 double position = fmod(t->color.position, 1.0) + fmod(s->seconds, 2.5) * 0.4;
99 double phase = (position - floor(position)) * 6;
100 int i = (int)phase;
101 double blend = phase - i;
102 rgb_pixel_t a = colors[i], b = colors[i + 1];
103 *t->color.out =
104 (rgb_pixel_t){(uint8_t)(a.r * (1 - blend) + b.r * blend), (uint8_t)(a.g * (1 - blend) + b.g * blend),
105 (uint8_t)(a.b * (1 - blend) + b.b * blend)};
106 return ASCIICHAT_OK;
107 }
109 if (t->type == ANIMATION_TARGET_COLOR && t->color.out) {
110 color_filter_calculate_rainbow((float)fmod(s->seconds, 3.5), &t->color.out->r, &t->color.out->g,
111 &t->color.out->b);
112 return ASCIICHAT_OK;
113 }
114 if (t->type != ANIMATION_TARGET_ANSI || !t->ansi.input || !t->ansi.out)
115 break;
116 *t->ansi.out = rainbow_render_ansi_at(t->ansi.input, (float)fmod(s->seconds, 3.5));
117 return *t->ansi.out ? ASCIICHAT_OK : SET_ERRNO(ERROR_MEMORY, "Rainbow output allocation failed");
119 if (t->type != ANIMATION_TARGET_ANSI || !t->ansi.input || !t->ansi.out || !t->ansi.rain)
120 break;
121 *t->ansi.out = digital_rain_render_at(t->ansi.rain, t->ansi.input, (float)s->seconds);
122 return *t->ansi.out ? ASCIICHAT_OK : SET_ERRNO(ERROR_MEMORY, "Digital rain output allocation failed");
125 break;
128 }
129 return SET_ERRNO(ERROR_INVALID_PARAM, "Animation type does not support this target");
130}
#define SET_ERRNO(code,...)
char * rainbow_render_ansi_at(const char *frame, float seconds)
asciichat_error_t test_pattern_render_at(struct test_pattern *pattern, int index, double time_ms, bool cadence)
char * digital_rain_render_at(digital_rain_t *rain, const char *frame, float seconds)
Named object registry for debugging — log identifiable resource names.
Matrix-style digital rain effect for ASCII frames.
unsigned char colors[(512 *256 *2) *3]
Definition fft.c:22
unsigned long long uint64_t
Definition common.h:63
unsigned char uint8_t
Definition common.h:60
#define NAMED_REGISTER(ptr, name, type, fmt, parent_ptr)
Register any pointer with base name, type, format spec, and location (auto-suffix).
#define NAMED_UNREGISTER(ptr)
Unregister a pointer.
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_MEMORY
Definition error_codes.h:51
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
void color_filter_calculate_rainbow(float time, uint8_t *r, uint8_t *g, uint8_t *b)
Calculate rainbow color from time (3.5s cycle).
🔢 Mathematical Utility Functions
static bool size_t gotel_query_t * out
Definition queries.h:8
🔤 String Manipulation and Shell Escaping Utilities
animation_hidden_policy_t hidden_policy
For animation config, this is the live record that ties type, fps, speed, hidden_policy together....
animation_config_t config
struct animation_target_t::@105141136260326341273057264343342151154253073027::@021005305237221242221055207105224353364212233103 test_pattern
struct animation_target_t::@105141136260326341273057264343342151154253073027::@072247246125252004245152136267001044326224304340 color
struct animation_target_t::@105141136260326341273057264343342151154253073027::@256117116162340230264137326272113315112047155330 ansi
struct test_pattern * context
struct digital_rain * rain
animation_target_type_t type
uint8_t b
Blue color component (0-255).
uint8_t g
Green color component (0-255).
uint8_t r
Red color component (0-255).
void animation_set_paused(animation_t *a, bool paused)
void animation_destroy(animation_t *a)
asciichat_error_t animation_update(animation_t *a, uint64_t now, animation_sample_t *out)
void animation_reset(animation_t *a)
asciichat_error_t animation_init(animation_t *a, const char *name, animation_config_t config)
asciichat_error_t animation_set_speed(animation_t *a, double speed)
asciichat_error_t animation_apply(const animation_sample_t *s, animation_target_t *t)
asciichat_error_t animation_sample_at(animation_config_t config, double seconds, animation_sample_t *out)
void animation_set_visible(animation_t *a, bool visible)
@ ANIMATION_HIDDEN_PAUSE
@ ANIMATION_HIDDEN_CONTINUE
@ ANIMATION_RAINBOW_FILTER
@ ANIMATION_DIGITAL_RAIN
@ ANIMATION_TEST_PATTERN
@ ANIMATION_SPLASH_RAINBOW
@ ANIMATION_TARGET_COLOR
@ ANIMATION_TARGET_TEST_PATTERN
@ ANIMATION_TARGET_ANSI