Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
diagnostic_reporter.hpp
Go to the documentation of this file.
1#pragma once
2
5
10#include <string>
11#include <sstream>
12#include <vector>
13#include <iomanip>
14#include <ctime>
15
16namespace pulp::format {
17
29public:
30 // ── Plugin info ──────────────────────────────────────────────────────
31
32 void set_plugin_info(const PluginDescriptor& desc, const state::StateStore& store) {
33 plugin_name_ = desc.name;
34 plugin_manufacturer_ = desc.manufacturer;
35 plugin_version_ = desc.version;
36 plugin_bundle_id_ = desc.bundle_id;
37 is_instrument_ = (desc.category == PluginCategory::Instrument);
38
39 // Capture parameter state
40 param_snapshot_.clear();
41 for (const auto& p : store.all_params()) {
42 ParamSnapshot snap;
43 snap.name = p.name;
44 snap.id = p.id;
45 snap.value = store.get_value(p.id);
46 snap.normalized = store.get_normalized(p.id);
47 snap.default_value = p.range.default_value;
48 snap.min = p.range.min;
49 snap.max = p.range.max;
50 snap.unit = p.unit;
51 param_snapshot_.push_back(snap);
52 }
53 }
54
55 // ── Audio config ─────────────────────────────────────────────────────
56
57 void set_audio_config(double sample_rate, int buffer_size,
58 int input_channels, int output_channels) {
59 sample_rate_ = sample_rate;
60 buffer_size_ = buffer_size;
61 input_channels_ = input_channels;
62 output_channels_ = output_channels;
63 }
64
65 void set_format_name(const std::string& name) { format_name_ = name; }
66 void set_host_name(const std::string& name) { host_name_ = name; }
67
68 // ── CPU load ─────────────────────────────────────────────────────────
69
70 void set_cpu_load(float load, float peak) {
71 cpu_load_ = load;
72 cpu_peak_ = peak;
73 }
74
75 // ── Custom entries ───────────────────────────────────────────────────
76
77 void add_custom_entry(const std::string& key, const std::string& value) {
78 custom_entries_.push_back({key, value});
79 }
80
81 // ── Report generation ────────────────────────────────────────────────
82
84 std::string generate_report() const {
85 std::ostringstream ss;
86 ss << std::fixed << std::setprecision(2);
87
88 ss << "=== Pulp Diagnostic Report ===\n";
89 ss << "Generated: " << timestamp() << "\n\n";
90
91 // System info
92 ss << "--- System ---\n";
93 ss << "Platform: " << os_name() << "\n";
94 ss << "Architecture: " << arch() << "\n\n";
95
96 // Plugin info
97 ss << "--- Plugin ---\n";
98 ss << "Name: " << plugin_name_ << "\n";
99 ss << "Manufacturer: " << plugin_manufacturer_ << "\n";
100 ss << "Version: " << plugin_version_ << "\n";
101 ss << "Bundle ID: " << plugin_bundle_id_ << "\n";
102 ss << "Type: " << (is_instrument_ ? "Instrument" : "Effect") << "\n";
103 if (!format_name_.empty()) ss << "Format: " << format_name_ << "\n";
104 if (!host_name_.empty()) ss << "Host: " << host_name_ << "\n";
105 ss << "\n";
106
107 // Audio config
108 ss << "--- Audio Configuration ---\n";
109 ss << "Sample Rate: " << sample_rate_ << " Hz\n";
110 ss << "Buffer Size: " << buffer_size_ << " samples\n";
111 ss << "Input Channels: " << input_channels_ << "\n";
112 ss << "Output Channels: " << output_channels_ << "\n";
113 if (cpu_load_ >= 0) {
114 ss << "CPU Load: " << (cpu_load_ * 100.0f) << "%\n";
115 ss << "CPU Peak: " << (cpu_peak_ * 100.0f) << "%\n";
116 }
117 ss << "\n";
118
119 // Parameters
120 ss << "--- Parameters (" << param_snapshot_.size() << ") ---\n";
121 for (const auto& p : param_snapshot_) {
122 ss << " [" << p.id << "] " << p.name << ": "
123 << p.value;
124 if (!p.unit.empty()) ss << " " << p.unit;
125 ss << " (norm=" << p.normalized
126 << ", range=" << p.min << ".." << p.max
127 << ", default=" << p.default_value << ")\n";
128 }
129 ss << "\n";
130
131 // Custom entries
132 if (!custom_entries_.empty()) {
133 ss << "--- Custom ---\n";
134 for (const auto& [key, value] : custom_entries_) {
135 ss << key << ": " << value << "\n";
136 }
137 ss << "\n";
138 }
139
140 ss << "=== End Report ===\n";
141 return ss.str();
142 }
143
145 std::string generate_json() const {
146 std::ostringstream ss;
147 ss << std::fixed << std::setprecision(4);
148
149 ss << "{\n";
150 ss << " \"timestamp\": \"" << json_escape(timestamp()) << "\",\n";
151 ss << " \"platform\": \"" << json_escape(os_name()) << "\",\n";
152 ss << " \"arch\": \"" << json_escape(arch()) << "\",\n";
153 ss << " \"plugin\": {\n";
154 ss << " \"name\": \"" << json_escape(plugin_name_) << "\",\n";
155 ss << " \"manufacturer\": \"" << json_escape(plugin_manufacturer_) << "\",\n";
156 ss << " \"version\": \"" << json_escape(plugin_version_) << "\",\n";
157 ss << " \"type\": \"" << (is_instrument_ ? "instrument" : "effect") << "\"\n";
158 ss << " },\n";
159 ss << " \"audio\": {\n";
160 ss << " \"sampleRate\": " << sample_rate_ << ",\n";
161 ss << " \"bufferSize\": " << buffer_size_ << ",\n";
162 ss << " \"inputChannels\": " << input_channels_ << ",\n";
163 ss << " \"outputChannels\": " << output_channels_ << "\n";
164 ss << " },\n";
165 ss << " \"parameters\": [\n";
166 for (size_t i = 0; i < param_snapshot_.size(); ++i) {
167 const auto& p = param_snapshot_[i];
168 ss << " {\"id\": " << p.id
169 << ", \"name\": \"" << json_escape(p.name)
170 << "\", \"value\": " << p.value
171 << ", \"normalized\": " << p.normalized << "}";
172 if (i + 1 < param_snapshot_.size()) ss << ",";
173 ss << "\n";
174 }
175 ss << " ]\n";
176 ss << "}\n";
177 return ss.str();
178 }
179
180private:
181 std::string plugin_name_;
182 std::string plugin_manufacturer_;
183 std::string plugin_version_;
184 std::string plugin_bundle_id_;
185 bool is_instrument_ = false;
186 std::string format_name_;
187 std::string host_name_;
188
189 double sample_rate_ = 0;
190 int buffer_size_ = 0;
191 int input_channels_ = 0;
192 int output_channels_ = 0;
193 float cpu_load_ = -1;
194 float cpu_peak_ = -1;
195
196 struct ParamSnapshot {
197 std::string name;
198 state::ParamID id = 0;
199 float value = 0;
200 float normalized = 0;
201 float default_value = 0;
202 float min = 0, max = 0;
203 std::string unit;
204 };
205 std::vector<ParamSnapshot> param_snapshot_;
206 std::vector<std::pair<std::string, std::string>> custom_entries_;
207
208 static std::string timestamp() {
209 auto now = std::time(nullptr);
210 char buf[64];
211 const auto local = runtime::localtime_local(now);
212 std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &local);
213 return buf;
214 }
215
216 static std::string json_escape(const std::string& text) {
217 std::string out;
218 out.reserve(text.size());
219 for (unsigned char c : text) {
220 switch (c) {
221 case '\"': out += "\\\""; break;
222 case '\\': out += "\\\\"; break;
223 case '\b': out += "\\b"; break;
224 case '\f': out += "\\f"; break;
225 case '\n': out += "\\n"; break;
226 case '\r': out += "\\r"; break;
227 case '\t': out += "\\t"; break;
228 default:
229 if (c < 0x20) {
230 static constexpr char hex[] = "0123456789abcdef";
231 out += "\\u00";
232 out += hex[(c >> 4) & 0x0f];
233 out += hex[c & 0x0f];
234 } else {
235 out.push_back(static_cast<char>(c));
236 }
237 break;
238 }
239 }
240 return out;
241 }
242
243 static std::string os_name() {
244 switch (platform::current_os) {
245 case platform::OS::macOS: return "macOS";
246 case platform::OS::iOS: return "iOS";
247 case platform::OS::Windows: return "Windows";
248 case platform::OS::Linux: return "Linux";
249 case platform::OS::Android: return "Android";
250 default: return "Unknown";
251 }
252 }
253
254 static std::string arch() {
255#if defined(__aarch64__) || defined(_M_ARM64)
256 return "arm64";
257#elif defined(__x86_64__) || defined(_M_X64)
258 return "x86_64";
259#elif defined(__i386__) || defined(_M_IX86)
260 return "x86";
261#else
262 return "unknown";
263#endif
264 }
265};
266
267} // namespace pulp::format
Collects and formats diagnostic information about the system, plugin configuration,...
Definition diagnostic_reporter.hpp:28
void add_custom_entry(const std::string &key, const std::string &value)
Definition diagnostic_reporter.hpp:77
void set_host_name(const std::string &name)
Definition diagnostic_reporter.hpp:66
void set_cpu_load(float load, float peak)
Definition diagnostic_reporter.hpp:70
std::string generate_report() const
Generate a full diagnostic report as a human-readable string.
Definition diagnostic_reporter.hpp:84
void set_format_name(const std::string &name)
Definition diagnostic_reporter.hpp:65
std::string generate_json() const
Generate a compact JSON report for programmatic consumption.
Definition diagnostic_reporter.hpp:145
void set_plugin_info(const PluginDescriptor &desc, const state::StateStore &store)
Definition diagnostic_reporter.hpp:32
void set_audio_config(double sample_rate, int buffer_size, int input_channels, int output_channels)
Definition diagnostic_reporter.hpp:57
Centralized parameter storage with lock-free value access.
Definition store.hpp:164
float get_value(ParamID id) const
Read a parameter's base value (lock-free).
Definition store.hpp:186
float get_normalized(ParamID id) const
Read a parameter's value mapped to [0, 1] (lock-free).
std::span< const ParamInfo > all_params() const
View of all registered parameters (in registration order).
Definition store.hpp:439
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
@ Instrument
Synth/sampler (receives MIDI, produces audio).
Definition plugin_descriptor.hpp:187
@ iOS
Definition detect.hpp:9
@ macOS
Definition detect.hpp:9
@ Windows
Definition detect.hpp:9
@ Android
Definition detect.hpp:9
@ Linux
Definition detect.hpp:9
constexpr OS current_os
Definition detect.hpp:16
std::tm localtime_local(std::time_t value)
Definition system.hpp:44
uint32_t ParamID
Unique parameter identifier, stable across plugin versions.
Definition parameter.hpp:55
Plugin metadata — declared once, immutable.
Definition plugin_descriptor.hpp:245
std::string bundle_id
Definition plugin_descriptor.hpp:248
std::string manufacturer
Definition plugin_descriptor.hpp:247
std::string name
Definition plugin_descriptor.hpp:246
PluginCategory category
Definition plugin_descriptor.hpp:250
std::string version
Semantic version string, e.g. "1.0.0".
Definition plugin_descriptor.hpp:249