94 lines
3.7 KiB
C++
94 lines
3.7 KiB
C++
#pragma once
|
|
|
|
#include <cerrno>
|
|
#include <filesystem>
|
|
#include <string>
|
|
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
#include <boost/json.hpp>
|
|
|
|
#include <modulus/types.hpp>
|
|
|
|
|
|
namespace vamp_test {
|
|
|
|
inline auto add_timing(boost::json::value &value) -> void {
|
|
auto &music = value.at("music");
|
|
music.at("metadata").as_object()["song_id"] = "fixture";
|
|
auto &measures = music.at("staves").as_array().front().at("measures").as_array();
|
|
auto &pages = value.at("presentation").at("pages").as_array();
|
|
while (measures.size() < 2 * pages.size() - 1) {
|
|
measures.push_back(boost::json::object{});
|
|
}
|
|
auto beat = [](std::size_t n) { return boost::json::object{{"numerator", n}, {"denominator", 1}}; };
|
|
auto clicks = boost::json::array{};
|
|
for (std::size_t i = 0; i < measures.size(); ++i) {
|
|
measures[i].as_object()["duration"] = beat(4);
|
|
for (std::size_t b = 0; b < 4; ++b) {
|
|
clicks.push_back(boost::json::object{{"beat", beat(i * 4 + b)}, {"downbeat", b == 0}});
|
|
}
|
|
}
|
|
std::size_t cursor{};
|
|
auto systems = boost::json::array{};
|
|
for (std::size_t i = 0; i < pages.size(); ++i) {
|
|
auto count = i + 1 == pages.size() ? measures.size() - cursor : 2U;
|
|
auto &page = pages[i].as_object();
|
|
page["first_measure"] = cursor + 1;
|
|
page["measure_count"] = count;
|
|
page["start_beat"] = beat(cursor * 4);
|
|
page["end_beat"] = beat((cursor + count) * 4);
|
|
auto members = boost::json::array{};
|
|
for (std::size_t j = 0; j < (i + 1 == pages.size() ? 1U : 2U); ++j) {
|
|
auto n = i + 1 == pages.size() ? count : 1U;
|
|
auto labels = boost::json::array{};
|
|
for (std::size_t k = 0; k < n; ++k) {
|
|
labels.push_back(boost::json::object{{"measure", cursor + k + 1}, {"bounds", boost::json::array{30 + k * 30, 70 + j * 220, 42 + k * 30, 82 + j * 220}}});
|
|
}
|
|
auto system = boost::json::object{{"first_measure", cursor + 1}, {"measure_count", n}, {"start_beat", beat(cursor * 4)}, {"end_beat", beat((cursor + n) * 4)}, {"labels", labels}};
|
|
members.push_back(system);
|
|
systems.push_back(system);
|
|
cursor += n;
|
|
}
|
|
page["systems"] = members;
|
|
}
|
|
auto playback = boost::json::array{};
|
|
for (std::size_t i = 0; i < systems.size(); ++i) {
|
|
auto page = pages[std::min(i / 2, pages.size() - 1)].as_object();
|
|
auto members = boost::json::array{systems[i]};
|
|
if (i + 1 < systems.size()) {
|
|
members.push_back(systems[i + 1]);
|
|
}
|
|
page["systems"] = members;
|
|
page["first_measure"] = members.front().at("first_measure");
|
|
page["start_beat"] = members.front().at("start_beat");
|
|
page["end_beat"] = members.back().at("end_beat");
|
|
page["measure_count"] = members.back().at("first_measure").to_number<std::size_t>() + members.back().at("measure_count").to_number<std::size_t>() - members.front().at("first_measure").to_number<std::size_t>();
|
|
playback.push_back(page);
|
|
}
|
|
value.at("presentation").as_object()["playback_pages"] = playback;
|
|
value.as_object()["performance"] = boost::json::object{{"song_id", "fixture"}, {"duration", beat(measures.size() * 4)}, {"count_in_beats", 4}, {"clicks", clicks}};
|
|
}
|
|
|
|
inline auto build_catalog(std::filesystem::path const &assets, std::filesystem::path const &database) -> std::bool_t {
|
|
auto source = assets.string();
|
|
auto destination = database.string();
|
|
auto child = ::fork();
|
|
BOOST_REQUIRE(child >= 0);
|
|
if (child == 0) {
|
|
::execl(VAMP_TEST_PYTHON, VAMP_TEST_PYTHON, VAMP_TEST_SOURCE_DIR "/generator/catalog.py", source.c_str(), destination.c_str(), nullptr);
|
|
::_exit(127);
|
|
}
|
|
auto status = std::int32_t{};
|
|
auto waited = ::waitpid(child, &status, 0);
|
|
while (waited < 0 && errno == EINTR) {
|
|
waited = ::waitpid(child, &status, 0);
|
|
}
|
|
BOOST_REQUIRE(waited == child);
|
|
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
|
}
|
|
|
|
}
|