ESPHome 2026.8.0b4
Loading...
Searching...
No Matches
sendspin_image.h
Go to the documentation of this file.
1#pragma once
2
4
5#if defined(USE_ESP32) && defined(USE_SENDSPIN_ARTWORK)
6
10
12
13#include <sendspin/artwork_role.h>
14
15#include <array>
16#include <cstdint>
17
18namespace esphome::sendspin_ {
19
26 public:
28
34 bool decoded_into(const uint8_t *buffer) const { return this->buffer_ == buffer; }
35};
36
43 public:
45
46 void set_frame(const uint8_t *data, int width, int height) {
47 this->data_start_ = data;
48 this->width_ = width;
49 this->height_ = height;
50#ifdef USE_LVGL
51 // Keep the descriptor LVGL is handed in step with the frame. This does not redraw anything:
52 // only setting a widget's source invalidates it.
53 this->get_lv_image_dsc();
54#endif
55 }
56
62 void set_showing_artwork(bool showing_artwork) { this->showing_artwork_ = showing_artwork; }
63
64 void set_placeholder(image::Image *placeholder) { this->placeholder_ = placeholder; }
65
66 void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override {
67 if (!this->showing_artwork_) {
68 // Nothing worth showing yet: the placeholder if there is one, otherwise leave the area be
69 // rather than paint a blank frame over it.
70 if (this->placeholder_ != nullptr) {
71 this->placeholder_->draw(x, y, display, color_on, color_off);
72 }
73 return;
74 }
75 image::Image::draw(x, y, display, color_on, color_off);
76 }
77
78 protected:
80 bool showing_artwork_{false};
81};
82
99 public:
100 SendspinImageSlot(uint8_t slot, ArtworkImageView *current_image, int width, int height,
102 bool is_big_endian)
103 : decode_sink_(format, type, transparency, nullptr, is_big_endian, width, height),
104 current_image_(current_image),
105 width_(width),
106 height_(height),
107 slot_(slot) {}
108
109 void setup() override;
110 void dump_config() override;
111
112 template<typename F> void add_on_image_display_callback(F &&callback) {
113 this->image_display_callback_.add(std::forward<F>(callback));
114 }
115 template<typename F> void add_on_image_clear_callback(F &&callback) {
116 this->image_clear_callback_.add(std::forward<F>(callback));
117 }
118 template<typename F> void add_on_image_error_callback(F &&callback) {
119 this->image_error_callback_.add(std::forward<F>(callback));
120 }
121
129 void set_transition_image(ArtworkImageView *transition_image) { this->transition_image_ = transition_image; }
130
137 void transition_finished();
138
139 protected:
140 void on_decode_(const uint8_t *data, size_t length);
141 bool decode_frame_(const uint8_t *data, size_t length, const uint8_t *target);
142 void on_display_(uint32_t lateness_ms);
143 void on_clear_();
144 void finish_transition_();
145 void apply_frames_(bool transition_is_artwork);
146 void report_error_();
147
149
150 // The two frame buffers, allocated in setup() and never freed. Their contents are written on the
151 // decode thread and read by whatever draws the views, so only their roles are swapped, never the
152 // pointers themselves.
153 std::array<uint8_t *, 2> buffers_{};
154
155 // pending_mutex_ guards the two fields below, the only state shared across threads. Everything
156 // after them is touched on the main loop only.
158 // Index into buffers_ of the frame the current image shows. buffers_[current_index_ ^ 1] holds
159 // the outgoing frame and is the next decode target. Written on the main loop, read on the
160 // decode thread.
161 uint8_t current_index_{0};
162 // Set on the decode thread once a frame is waiting in buffers_[current_index_ ^ 1].
163 bool frame_pending_{false};
164
165 // True once artwork has been displayed, until the next clear; decides whether the outgoing frame
166 // is real artwork or the black the buffers start as. Main loop only.
167 bool showing_artwork_{false};
168 // True while a displayed frame awaits transition_finished(); gates duplicate or stray calls
169 // so exactly one ack reaches the library per delivery. Main loop only.
171
176 uint8_t slot_;
177
181};
182
183} // namespace esphome::sendspin_
184
185#endif
Mutex implementation, with API based on the unavailable std::mutex.
Definition helpers.h:1930
const uint8_t * data_start_
Definition image.h:54
Image(const uint8_t *data_start, int width, int height, ImageType type, Transparency transparency)
Definition image.cpp:215
lv_image_dsc_t * get_lv_image_dsc()
Definition image.cpp:107
void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override
Definition image.cpp:8
A dynamic image that can be loaded and decoded at runtime.
RuntimeImage(ImageFormat format, image::ImageType type, image::Transparency transparency, image::Image *placeholder=nullptr, bool is_big_endian=false, int fixed_width=0, int fixed_height=0)
Construct a new RuntimeImage object.
Decode-only RuntimeImage that decodes into a buffer owned by SendspinImageSlot.
bool decoded_into(const uint8_t *buffer) const
True when the decode ended with the given buffer still in place.
A non-owning image::Image view over a buffer owned by SendspinImageSlot.
void set_frame(const uint8_t *data, int width, int height)
void set_showing_artwork(bool showing_artwork)
Records whether the frame on show is real artwork rather than the black it starts as.
void set_placeholder(image::Image *placeholder)
void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override
Base class for all sendspin subcomponents.
A single artwork slot: owns the frame buffers and publishes them to its image views.
LazyCallbackManager< void()> image_error_callback_
void on_display_(uint32_t lateness_ms)
void add_on_image_display_callback(F &&callback)
void transition_finished()
Signals that the display transition for the last frame has finished.
void on_decode_(const uint8_t *data, size_t length)
void apply_frames_(bool transition_is_artwork)
LazyCallbackManager< void()> image_clear_callback_
bool decode_frame_(const uint8_t *data, size_t length, const uint8_t *target)
void set_transition_image(ArtworkImageView *transition_image)
Sets the optional view a transition draws the outgoing artwork from.
SendspinImageSlot(uint8_t slot, ArtworkImageView *current_image, int width, int height, runtime_image::ImageFormat format, image::ImageType type, image::Transparency transparency, bool is_big_endian)
LazyCallbackManager< void(uint32_t)> image_display_callback_
std::array< uint8_t *, 2 > buffers_
uint16_t type
ImageFormat
Image format types that can be decoded dynamically.
const char int const __FlashStringHelper * format
Definition log.h:74
static void uint32_t
uint16_t length
Definition tt21100.cpp:0
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6