2 #include <ossia/network/value/detail/value_conversion_impl.hpp>
7 #include <AvndProcesses/AddressTools.hpp>
8 #include <halp/audio.hpp>
18 halp_meta(name,
"CSV recorder")
19 halp_meta(author,
"ossia team")
20 halp_meta(category,
"Control/Recording")
21 halp_meta(description,
"Record the messages of a device at regular interval")
22 halp_meta(c_name,
"avnd_device_recorder")
23 halp_meta(uuid,
"7161ca22-5684-48f2-bde7-88933500a7fb")
30 std::vector<ossia::net::node_base*> roots;
31 std::chrono::steady_clock::time_point first_ts;
32 fmt::memory_buffer buf;
38 auto filename = QByteArray::fromStdString(this->filename);
39 filename.replace(
"%t", QDateTime::currentDateTimeUtc().toString().toUtf8());
40 f.setFileName(filename);
41 if(filename.isEmpty())
44 f.open(QIODevice::WriteOnly);
49 for(
auto in : this->roots)
51 if(
auto p = in->get_parameter())
54 f.write(QByteArray::fromStdString(p->get_node().osc_address()));
60 first_ts = std::chrono::steady_clock::now();
69 using namespace std::chrono;
70 const auto ts = duration_cast<std::chrono::milliseconds>(
71 std::chrono::steady_clock::now() - first_ts)
75 void write(int64_t timestamp)
77 f.write(QString::number(timestamp).toUtf8());
78 for(
auto in : this->roots)
80 if(
auto p = in->get_parameter())
85 ossia::apply(ossia::detail::fmt_writer{buf}, p->value());
86 f.write(buf.data(), buf.size());
93 std::shared_ptr<recorder_thread> impl = std::make_shared<recorder_thread>();
98 std::vector<ossia::net::node_base*> roots;
102 swap(
self.filename, path);
103 swap(
self.roots, roots);
114 swap(
self.filename, path);
124 = ossia::variant<reset_message, reset_path_message, process_message>;
128 std::function<void(std::shared_ptr<recorder_thread>, worker_message)> request;
129 static void work(std::shared_ptr<recorder_thread> t, worker_message&& mess)
132 [&]<
typename M>(M&& msg) { std::forward<M>(msg)(*t); }, std::move(mess));
139 PatternSelector pattern;
140 halp::time_chooser<
"Interval"> time;
141 struct : halp::lineedit<
"File pattern",
"">
143 void update(DeviceRecorder&
self)
145 self.worker.request(
self.impl, reset_path_message{
self.inputs.filename});
154 using tick = halp::tick_musical;
156 void operator()(
const halp::tick_musical& tk)
158 int64_t elapsed_ns = 0.;
159 if(!first_message_sent_pos)
160 first_message_sent_pos = tk.position_in_nanoseconds;
161 if(last_message_sent_pos)
162 elapsed_ns = tk.position_in_nanoseconds - *last_message_sent_pos;
164 if(elapsed_ns > 0 && elapsed_ns < inputs.time.value * 1e9)
166 last_message_sent_pos = tk.position_in_nanoseconds;
171 if(!std::exchange(started,
true))
173 inputs.pattern.reprocess();
174 worker.request(impl, reset_message{inputs.filename, roots});
177 worker.request(impl, process_message{});
181 std::optional<int64_t> first_message_sent_pos;
182 std::optional<int64_t> last_message_sent_pos;