FastLED 3.10.6
Loading...
Searching...
No Matches
fled.cpp.hpp
Go to the documentation of this file.
1#include "fl/fled/fled.h"
2
7#include "fl/math/screenmap.h"
8#include "fl/stl/flat_map.h"
9#include "fl/stl/json.h"
10#include "fl/stl/move.h"
11#include "fl/stl/noexcept.h"
12#include "fl/stl/shared_ptr.h"
13#include "fl/stl/span.h"
14#include "fl/stl/string.h"
15#include "fl/stl/vector.h"
16#include "fl/fs/fs.h"
17
18namespace fl {
19
20namespace {
21
23 static fl::json sEmpty;
24 return sEmpty;
25}
26
27} // namespace
28
29// ---- factories ----
30
31Fled Fled::load(FileSystem &fs, const char *path) FL_NO_EXCEPT {
32 fl::ifstream in = fs.openRead(path);
33 if (!in.is_open()) {
34 return Fled();
35 }
36 const fl::size total = in.size();
38 buf.resize(total);
39 if (total > 0) {
40 const fl::size got = in.read(buf.data(), total);
41 if (got != total) {
42 return Fled();
43 }
44 }
45 return Fled::loadFromVector(fl::move(buf));
46}
47
50 fl::json env;
51 if (!fl::fled::parseHeaderAndEnvelope(bytes.data(), bytes.size(), &hdr,
52 &env)) {
53 return Fled();
54 }
56 bytes, hdr.version, hdr.pixelFormat, hdr.payloadOffset, env));
57}
58
61 fl::json env;
62 if (!fl::fled::parseHeaderAndEnvelope(bytes.data(), bytes.size(), &hdr,
63 &env)) {
64 return Fled();
65 }
67 fl::move(bytes), hdr.version, hdr.pixelFormat, hdr.payloadOffset, env));
68}
69
70// ---- ctors / observers ----
71
73
76
77Fled::operator bool() const FL_NO_EXCEPT { return static_cast<bool>(mImpl); }
78
79// ---- header info ----
80
82 return mImpl ? mImpl->versionByte() : fl::u8(0);
83}
84
86 return mImpl ? mImpl->pixelFormatByte() : fl::u8(0);
87}
88
90 return mImpl ? fl::fled::bytesPerLed(mImpl->pixelFormatByte()) : fl::u8(0);
91}
92
94 return mImpl ? mImpl->payloadLen() : fl::size(0);
95}
96
97fl::size Fled::frameCount(fl::size ledCount) const FL_NO_EXCEPT {
98 if (!mImpl || ledCount == 0) return 0;
99 const fl::u8 bpp = fl::fled::bytesPerLed(mImpl->pixelFormatByte());
100 if (bpp == 0) return 0;
101 const fl::size perFrame = ledCount * static_cast<fl::size>(bpp);
102 if (perFrame == 0) return 0;
103 return mImpl->payloadLen() / perFrame;
104}
105
106// ---- JSON ----
107
109 if (!mImpl) {
110 return nullJson();
111 }
112 return mImpl->envelope();
113}
114
116 if (!mImpl) return 0;
117 return static_cast<fl::size>(mImpl->envelope().keys().size());
118}
119
120float Fled::videoFps(float defaultFps) const FL_NO_EXCEPT {
121 if (!mImpl) return defaultFps;
122 const fl::json &env = mImpl->envelope();
123 if (!env.contains(fl::string("video")) || !env["video"].is_object()) {
124 return defaultFps;
125 }
126 const fl::json videoNode = env["video"];
127 if (!videoNode.contains(fl::string("fps"))) {
128 return defaultFps;
129 }
130 auto fpsOpt = videoNode["fps"].as_float();
131 if (!fpsOpt) return defaultFps;
132 return static_cast<float>(*fpsOpt);
133}
134
136 if (!out) return fled::ColorStatus::NullOutput;
137 if (!mImpl) {
138 // Null bundle: no envelope, no header. Resolve as an undeclared
139 // rgb8 payload so callers get the historical default tuple.
140 return fled::resolveVideoColor(nullJson(),
141 static_cast<fl::u8>(fled::PixelFormat::Rgb8),
142 out);
143 }
144 return fled::resolveVideoColor(mImpl->envelope(), pixelFormat(), out);
145}
146
147bool Fled::videoFrame(fl::size frameIndex, fl::size ledCount,
149 if (!mImpl || !out || ledCount == 0) {
150 return false;
151 }
152 fled::PixelStorage storage;
154 &storage)) {
155 return false;
156 }
159 return false;
160 }
161 const fl::size bytesPerLed = fled::bytesPerLed(pixelFormat());
162 const fl::size payloadBytes = mImpl->payloadLen();
163 if (bytesPerLed == 0 || ledCount > payloadBytes / bytesPerLed) {
164 return false;
165 }
166 const fl::size stride = ledCount * bytesPerLed;
167 if (stride == 0 || payloadBytes % stride != 0 ||
168 frameIndex >= payloadBytes / stride) {
169 return false;
170 }
171 fl::size completePayloadBytes = 0;
172 fl::shared_ptr<const fl::u8> payload = blob("frame_payload",
173 &completePayloadBytes);
174 if (!payload) {
175 return false;
176 }
177 const fl::size offset = frameIndex * stride;
178 out->mStorage = storage;
179 out->mColor = color;
180 out->mPayload = fl::shared_ptr<const fl::u8>(payload, payload.get() + offset);
181 out->mPayloadBytes = stride;
182 out->mStride = stride;
183 return true;
184}
185
186// ---- blobs ----
187
189 fl::size *outLen) const FL_NO_EXCEPT {
190 if (outLen) *outLen = 0;
191 if (!mImpl) {
193 }
194 if (!fl::fled::sectionNameIsPayload(sectionName)) {
196 }
197 const fl::size n = mImpl->payloadLen();
198 if (n == 0) {
200 }
201 const fl::u8 *raw = mImpl->bytes() + mImpl->payloadOffset();
202 if (outLen) *outLen = n;
203 // Aliasing ctor: pins mImpl alive while the returned ptr is held.
204 // NOTE: for loadFromStatic, the bytes themselves still live in the
205 // caller's static span - see Fled::loadFromStatic contract.
207}
208
209// ---- typed section accessors ----
210
212 if (!mImpl) {
214 }
215 const fl::json &env = mImpl->envelope();
216 // The v1 envelope carries the screen map under the "map" key. The
217 // canonical parser is ScreenMap::ParseJson, which takes a JSON
218 // document containing a top-level "map" object - exactly the shape
219 // of the envelope, so we hand it straight to ParseJson.
220 if (!env.contains(fl::string("map")) || !env["map"].is_object()) {
222 }
223 fl::string envText = env.to_string();
225 if (!ScreenMap::ParseJson(envText.c_str(), &segments)) {
227 }
228 if (segments.empty()) {
230 }
231 // Single-strip path: return the first segment. Multi-strip support
232 // would be a dedicated accessor (out of scope here).
233 ScreenMap &first = segments.begin()->second;
234 return fl::make_shared<ScreenMap>(first);
235}
236
238 // TODO: construct MultiChannelConfig from envelope["channels"] once
239 // the MultiChannelConfig JSON deserializer lands in fl/channels/.
241}
242
243} // namespace fl
fl::u8 pixelFormat() const FL_NO_EXCEPT
Definition fled.cpp.hpp:85
static Fled loadFromStatic(fl::span< const fl::u8 > bytes) FL_NO_EXCEPT
Definition fled.cpp.hpp:48
fl::size sectionCount() const FL_NO_EXCEPT
Definition fled.cpp.hpp:115
fl::size payloadBytes() const FL_NO_EXCEPT
Definition fled.cpp.hpp:93
fl::shared_ptr< const fl::u8 > blob(const char *sectionName, fl::size *outLen) const FL_NO_EXCEPT
Definition fled.cpp.hpp:188
const fl::json & json() const FL_NO_EXCEPT
Definition fled.cpp.hpp:108
fl::size frameCount(fl::size ledCount) const FL_NO_EXCEPT
Definition fled.cpp.hpp:97
fled::ColorStatus videoColor(fled::VideoColor *out) const FL_NO_EXCEPT
Definition fled.cpp.hpp:135
fl::u8 bytesPerLed() const FL_NO_EXCEPT
Definition fled.cpp.hpp:89
Fled() FL_NO_EXCEPT
Definition fled.cpp.hpp:72
bool videoFrame(fl::size frameIndex, fl::size ledCount, fled::VideoFrameView *out) const FL_NO_EXCEPT
Definition fled.cpp.hpp:147
fl::shared_ptr< ScreenMap > screenMap() const FL_NO_EXCEPT
Definition fled.cpp.hpp:211
fl::shared_ptr< MultiChannelConfig > channels() const FL_NO_EXCEPT
Definition fled.cpp.hpp:237
fl::shared_ptr< fled::FledImpl > mImpl
Definition fled.h:156
float videoFps(float defaultFps=30.0f) const FL_NO_EXCEPT
Definition fled.cpp.hpp:120
static Fled loadFromVector(fl::vector< fl::u8 > &&bytes) FL_NO_EXCEPT
Definition fled.cpp.hpp:59
fl::u8 version() const FL_NO_EXCEPT
Definition fled.cpp.hpp:81
static Fled load(FileSystem &fs, const char *path) FL_NO_EXCEPT
Definition fled.cpp.hpp:31
static bool ParseJson(const char *jsonStrScreenMap, fl::flat_map< string, ScreenMap > *segmentMaps, string *err=nullptr) FL_NO_EXCEPT
const char * c_str() const FL_NO_EXCEPT
iterator begin() FL_NO_EXCEPT
Definition flat_map.h:85
bool empty() const FL_NO_EXCEPT
Definition flat_map.h:99
fl::size_t size() const
Definition fstream.h:146
ifstream & read(char *buffer, fl::size_t count)
bool is_open() const
Definition fstream.h:111
bool is_object() const FL_NO_EXCEPT
Definition json.h:391
fl::string to_string() const FL_NO_EXCEPT
Definition json.h:836
fl::optional< float > as_float() const FL_NO_EXCEPT
Definition json.h:409
bool contains(size_t idx) const FL_NO_EXCEPT
Definition json.h:790
T * get() const FL_NO_EXCEPT
Definition shared_ptr.h:334
void resize(fl::size n) FL_NO_EXCEPT
Definition vector.h:593
T * data() FL_NO_EXCEPT
Definition vector.h:619
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
FastLED's Elegant JSON Library: fl::json
const fl::json & nullJson() FL_NO_EXCEPT
Definition fled.cpp.hpp:22
bool parseHeaderAndEnvelope(const fl::u8 *data, fl::size len, ParsedHeader *outHeader, fl::json *outEnvelope) FL_NO_EXCEPT
fl::u8 bytesPerLed(fl::u8 pixelFormat) FL_NO_EXCEPT
ColorStatus resolveVideoColor(const fl::json &envelope, fl::u8 pixelFormat, VideoColor *out) FL_NO_EXCEPT
ColorStatus
Definition color.h:54
bool toPixelStorage(PixelFormat fledFormat, PixelStorage *out) FL_NO_EXCEPT
bool sectionNameIsPayload(const char *name) FL_NO_EXCEPT
unsigned char u8
Definition stdint.h:131
constexpr remove_reference< T >::type && move(T &&t) FL_NO_EXCEPT
Definition move.h:28
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
Definition shared_ptr.h:414
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
Base definition for an LED controller.
Definition crgb.hpp:179