Initial public khodo snapshot
ci / checks (push) Successful in 38m58s

This commit is contained in:
khodowany
2026-09-04 19:30:11 -05:00
commit 4f9a269f85
99 changed files with 59585 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <cstdint>
#if defined(__has_include)
#if __has_include(<stdfloat>)
#include <stdfloat>
#endif
#endif
namespace std {
using bool_t = decltype(true);
using char_t = decltype('x');
using uchar_t = std::uint8_t;
#if !defined(__STDCPP_FLOAT32_T__)
using float32_t = decltype(0.0F);
#endif
#if !defined(__STDCPP_FLOAT64_T__)
using float64_t = decltype(0.0);
#endif
}
+73
View File
@@ -0,0 +1,73 @@
#pragma once
#ifndef NO_SYS
#define NO_SYS 1
#endif
#ifndef LWIP_SOCKET
#define LWIP_SOCKET 0
#endif
#define LWIP_NETCONN 0
#define MEM_LIBC_MALLOC 0
#define MEM_ALIGNMENT 4
#define MEM_SIZE 16000
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define LWIP_DHCP 1
#define LWIP_DNS 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define LWIP_CHKSUM_ALGORITHM 3
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
#define TCP_MSS 1460
#define TCP_WND (8 * TCP_MSS)
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * TCP_SND_BUF + TCP_MSS - 1) / TCP_MSS)
#define MEM_STATS 0
#define SYS_STATS 0
#define MEMP_STATS 0
#define LINK_STATS 0
#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <array>
#include <cstdint>
#include <types.hpp>
#include <vamp_style.hpp>
namespace vamp_pico {
constexpr auto display_width = std::int32_t{320};
constexpr auto display_height = std::int32_t{240};
constexpr auto color_black = std::uint16_t{0x0000};
constexpr auto color_white = std::uint16_t{0xffff};
constexpr auto color_gray = std::uint16_t{0x8410};
class display {
public:
auto init() -> void;
auto fill(std::uint16_t color) -> void;
auto fill_rect(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height, std::uint16_t color) -> void;
auto draw_text(std::int32_t x, std::int32_t y, std::char_t const* text, std::uint16_t color, std::int32_t scale = 2) -> void;
auto show_boot(std::char_t const* line1, std::char_t const* line2, std::uint16_t accent) -> void;
auto show_remote(vamp_style::color status, std::char_t const* title, std::char_t const* part, std::uint32_t page, std::uint32_t pages, std::bool_t active) -> void;
private:
std::bool_t remote_valid_{};
vamp_style::color last_status_{};
std::bool_t last_active_{};
std::array<std::char_t, 96> last_title_{};
std::array<std::char_t, 48> last_part_{};
std::uint32_t last_page_{};
std::uint32_t last_pages_{};
};
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include <vamp_protocol/page_control.hpp>
#include <types.hpp>
namespace vamp_pico {
struct remote_display_state {
std::bool_t active{};
std::char_t title[96]{};
std::char_t part[48]{};
std::char_t mode[24]{};
std::uint32_t page{};
std::uint32_t pages{};
};
auto post_remote_command(vamp_protocol::page_command command, vamp_pico::remote_display_state& state) -> std::bool_t;
auto heartbeat() -> std::bool_t;
auto fetch_remote_display(vamp_pico::remote_display_state& state) -> std::bool_t;
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <cstdint>
#include <types.hpp>
namespace vamp_pico {
struct touch_point {
std::int32_t x{};
std::int32_t y{};
};
class touch_controller {
public:
auto init() -> void;
auto read(touch_point& point) -> std::bool_t;
};
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <types.hpp>
namespace vamp_protocol {
constexpr std::char_t root_path[] = "/";
constexpr std::char_t status_path[] = "/api/status";
constexpr std::char_t next_page_path[] = "/api/page/next";
constexpr std::char_t previous_page_path[] = "/api/page/previous";
constexpr std::char_t remote_next_path[] = "/api/remote/next";
constexpr std::char_t remote_previous_path[] = "/api/remote/previous";
constexpr std::char_t remote_select_path[] = "/api/remote/select";
constexpr std::char_t remote_heartbeat_path[] = "/api/remote/heartbeat";
constexpr std::char_t remote_display_path[] = "/api/remote/display";
enum class page_command {
PREVIOUS,
NEXT,
SELECT,
};
auto page_command_path(vamp_protocol::page_command command) -> std::char_t const*;
auto page_command_legacy_path(vamp_protocol::page_command command) -> std::char_t const*;
auto page_command_name(vamp_protocol::page_command command) -> std::char_t const*;
auto page_command_display_label(vamp_protocol::page_command command) -> std::char_t const*;
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <cstdint>
#include <types.hpp>
namespace vamp_style {
struct color {
std::uint8_t r{};
std::uint8_t g{};
std::uint8_t b{};
std::uint8_t a{255};
};
constexpr auto background = vamp_style::color{9, 12, 14, 255};
constexpr auto panel = vamp_style::color{21, 27, 30, 255};
constexpr auto ink = vamp_style::color{238, 244, 241, 255};
constexpr auto muted = vamp_style::color{137, 151, 149, 255};
constexpr auto rule = vamp_style::color{66, 78, 78, 255};
constexpr auto paper = vamp_style::color{2, 3, 3, 255};
constexpr auto paper_ink = vamp_style::color{246, 248, 244, 255};
constexpr auto accent = vamp_style::color{232, 190, 70, 255};
constexpr auto selection = vamp_style::color{41, 100, 111, 255};
constexpr auto connecting = vamp_style::color{45, 111, 185, 255};
constexpr auto retrying = vamp_style::color{229, 171, 37, 255};
constexpr auto connected = vamp_style::color{40, 170, 88, 255};
constexpr auto danger = vamp_style::color{190, 63, 58, 255};
auto rgb565(vamp_style::color value) -> std::uint16_t;
}
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <array>
#include <cstdint>
#include <string_view>
#include <types.hpp>
namespace vamp_style {
constexpr auto ui_font_path = std::string_view{"/usr/share/product-vamp/fonts/petaluma/PetalumaScript.otf"};
constexpr auto score_text_font_path = std::string_view{"/usr/share/product-vamp/fonts/petaluma/PetalumaScript.otf"};
constexpr auto score_music_font_path = std::string_view{"/usr/share/product-vamp/fonts/petaluma/Petaluma.otf"};
constexpr auto ui_font_height = std::int32_t{36};
constexpr auto ui_font_max_width = std::int32_t{28};
struct font_glyph {
std::array<std::uint8_t, ui_font_height * ui_font_max_width> alpha{};
std::uint8_t width{};
std::uint8_t advance{};
};
auto ui_font_glyph(std::char_t value) -> vamp_style::font_glyph;
auto ui_font_pair_adjust(std::char_t left, std::char_t right) -> std::int32_t;
auto ui_text_width(std::string_view text, std::int32_t scale) -> std::int32_t;
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <cstdint>
#include <expected>
#include <string>
#include <modulus.hpp>
#include <types.hpp>
namespace vamp_zero {
struct command_line {
std::string config_path{"/etc/product-vamp/vamp.json"};
std::bool_t check_config{};
std::bool_t health_check{};
std::bool_t print_version{};
std::bool_t exit_after_startup{};
std::bool_t migrate{};
};
auto parse_command_line(std::int32_t argc, std::char_t** argv) -> std::expected<vamp_zero::command_line, modulus::error>;
auto run(vamp_zero::command_line command) -> std::expected<void, modulus::error>;
}
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <luma.hpp>
#include <vamp_style.hpp>
namespace vamp_zero {
auto to_luma(vamp_style::color value) -> luma::color;
}
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include <chrono>
#include <expected>
#include <string>
#include <boost/json/value.hpp>
#include <ligo.hpp>
#include <luma.hpp>
#include <modulus.hpp>
#include <types.hpp>
#include <vamp_zero/types.hpp>
namespace vamp_zero {
struct runtime_config {
vamp_zero::hardware_mode hardware{vamp_zero::hardware_mode::REAL};
std::bool_t headless{false};
std::bool_t exit_after_startup{false};
std::string assets_path{"/usr/share/product-vamp"};
std::string heartbeat_path{"/run/product-vamp/heartbeat.json"};
};
struct database_config {
std::string path{"/var/lib/product-vamp/vamp.db"};
std::string migrations_path{"/usr/share/product-vamp/migrations"};
};
struct control_config {
ligo::endpoint_config endpoint{
.name = "product-vamp-control",
.protocol = ligo::protocol::HTTP,
.bind = "0.0.0.0:8080",
.timeout = std::chrono::milliseconds{5000},
.http = {
.max_body_size = 64U * 1024U,
},
};
std::string ap_ssid{"Vamp Control"};
std::string ap_passphrase{"vamp-control"};
std::string ap_interface{"wlan0"};
std::string zero_ip{"192.168.42.1"};
std::string zero_cidr{"192.168.42.1/24"};
};
struct config {
modulus::config modulus{};
vamp_zero::runtime_config runtime{};
vamp_zero::database_config database{};
vamp_zero::control_config control{};
luma::application_config display{.title = "Product Vamp"};
};
auto parse_config(boost::json::value const& value) -> std::expected<vamp_zero::config, modulus::error>;
auto load_config(std::string const& path) -> std::expected<vamp_zero::config, modulus::error>;
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <expected>
#include <string>
#include <vector>
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/awaitable.hpp>
#include <modulus.hpp>
#include <vamp_zero/config.hpp>
#include <vamp_zero/types.hpp>
namespace vamp_zero {
auto async_migrate_database(boost::asio::any_io_executor executor, vamp_zero::database_config config) -> boost::asio::awaitable<std::expected<void, modulus::error>>;
auto async_import_catalogs(boost::asio::any_io_executor executor, vamp_zero::database_config config, std::string assets_path) -> boost::asio::awaitable<std::expected<void, modulus::error>>;
auto async_load_performance_library(boost::asio::any_io_executor executor, vamp_zero::database_config config) -> boost::asio::awaitable<std::expected<vamp_zero::library_state, modulus::error>>;
auto async_load_practice_library(boost::asio::any_io_executor executor, vamp_zero::database_config config) -> boost::asio::awaitable<std::expected<vamp_zero::practice_library, modulus::error>>;
auto split_migration_statements(std::string const& input) -> std::expected<std::vector<std::string>, modulus::error>;
}
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include <cstdint>
#include <expected>
#include <string>
#include <utility>
#include <modulus.hpp>
namespace vamp_zero {
enum class error_code : std::int32_t {
OK = 0,
INVALID_ARGUMENT = 1,
NOT_FOUND = 2,
UNAVAILABLE = 3,
PERSISTENCE = 4,
CONFLICT = 5,
INTERNAL = 6,
};
auto make_error(vamp_zero::error_code code, std::string message, modulus::source_location location = modulus::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION())) -> modulus::error;
auto fail_void(vamp_zero::error_code code, std::string message, modulus::source_location location = modulus::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION())) -> std::expected<void, modulus::error>;
template <typename VALUE>
auto fail(vamp_zero::error_code code, std::string message, modulus::source_location location = modulus::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION())) -> std::expected<VALUE, modulus::error>;
}
template <typename VALUE>
auto vamp_zero::fail(vamp_zero::error_code code, std::string message, modulus::source_location location) -> std::expected<VALUE, modulus::error> {
return modulus::fail<VALUE>(vamp_zero::make_error(code, std::move(message), location));
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <expected>
#include <string>
#include <string_view>
#include <vector>
#include <modulus.hpp>
#include <vamp_zero/types.hpp>
namespace vamp_zero {
auto parse_score_document(std::string_view json, std::string source_path = {}) -> std::expected<vamp_zero::score_document, modulus::error>;
auto load_performance_library(std::string const& assets_path) -> std::expected<vamp_zero::library_state, modulus::error>;
auto load_practice_library(std::string const& assets_path) -> std::expected<vamp_zero::practice_library, modulus::error>;
auto group_library_parts(std::vector<vamp_zero::library_part> parts) -> vamp_zero::library_state;
auto group_practice_exercises(std::vector<vamp_zero::practice_exercise> exercises) -> vamp_zero::practice_library;
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <expected>
#include <string>
#include <boost/json/value.hpp>
#include <modulus.hpp>
#include <vamp_protocol/page_control.hpp>
#include <vamp_zero/types.hpp>
namespace vamp_zero {
auto apply_app_command(vamp_zero::app_state state, vamp_protocol::page_command command) -> vamp_zero::app_state;
auto app_status_json(vamp_zero::app_state const& state) -> boost::json::value;
auto remote_display_text(vamp_zero::app_state const& state) -> std::string;
auto validate_app_state(vamp_zero::app_state const& state) -> std::expected<void, modulus::error>;
}
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include <functional>
#include <chrono>
#include <mutex>
#include <optional>
#include <boost/json/value.hpp>
#include <ligo.hpp>
#include <vamp_protocol/page_control.hpp>
#include <vamp_zero/config.hpp>
#include <vamp_zero/types.hpp>
namespace vamp_zero {
class control_state {
public:
using observer = std::function<void(vamp_zero::app_state)>;
control_state(vamp_zero::config config, vamp_zero::app_state state);
auto config() const -> vamp_zero::config;
auto snapshot() const -> vamp_zero::app_state;
auto apply(vamp_protocol::page_command command) -> vamp_zero::app_state;
auto heartbeat() -> vamp_zero::app_state;
auto refresh_connection() -> std::optional<vamp_zero::app_state>;
auto set_observer(vamp_zero::control_state::observer observer) -> void;
private:
auto pico_connected_locked() const -> std::bool_t;
auto snapshot_locked() const -> vamp_zero::app_state;
mutable std::mutex mutex_{};
vamp_zero::config config_{};
vamp_zero::app_state state_{};
std::chrono::steady_clock::time_point last_heartbeat_{};
vamp_zero::control_state::observer observer_{};
};
auto make_router(vamp_zero::control_state& state) -> ligo::service_router;
auto portal_status_json(vamp_zero::config const& config, vamp_zero::app_state const& state) -> boost::json::value;
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <cstddef>
#include <luma.hpp>
#include <vamp_zero/types.hpp>
namespace vamp_zero {
constexpr auto score_measures_per_system = std::size_t{4};
constexpr auto score_systems_per_page = std::size_t{3};
constexpr auto score_measures_per_page = score_measures_per_system * score_systems_per_page;
auto draw_score_page(luma::draw_context& context, luma::rect bounds, vamp_zero::score_document const& score, std::size_t page_index) -> void;
}
+162
View File
@@ -0,0 +1,162 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
#include <types.hpp>
namespace vamp_zero {
enum class hardware_mode {
FAKE,
REAL,
};
struct score_pitch {
std::char_t letter{'c'};
std::int32_t octave{};
std::string accidental{};
};
struct score_note {
std::string id{};
std::string kind{};
std::bool_t hidden{};
std::int64_t duration_ticks{};
std::int64_t display_ticks{};
std::string notehead{};
std::string chord_symbol{};
std::string lyric{};
std::bool_t tie_to_next{};
std::bool_t tie_from_previous{};
std::vector<vamp_zero::score_pitch> pitches{};
};
struct score_measure {
std::string id{};
std::string section_label{};
std::string time_signature{};
std::string key_signature{};
std::vector<vamp_zero::score_note> notes{};
};
struct score_document {
std::string id{};
std::string title{};
std::string composer{};
std::string key_signature{};
std::string part{};
std::string arrangement_part_type{};
std::string source_path{};
std::string source_json{};
std::vector<vamp_zero::score_measure> measures{};
};
struct library_part {
std::string id{};
std::string title{};
std::string composer{};
std::string key_signature{};
std::string part{};
std::string source_path{};
std::string source_json{};
std::size_t measure_count{};
std::size_t total_pages{};
};
struct song_group {
std::string title{};
std::string composer{};
std::vector<vamp_zero::library_part> parts{};
};
struct library_state {
std::vector<vamp_zero::library_part> parts{};
std::vector<vamp_zero::song_group> groups{};
};
struct practice_exercise {
struct score_variant {
std::string id{};
std::string key_signature{};
std::string source_path{};
std::string source_json{};
std::size_t measure_count{};
std::size_t total_pages{};
};
std::string id{};
std::string practice_type_id{};
std::string practice_type_title{};
std::string lesson_group_id{};
std::string lesson_group_title{};
std::string title{};
std::string composer{};
std::string key_signature{};
std::string source_path{};
std::string source_json{};
std::size_t measure_count{};
std::size_t total_pages{};
std::vector<vamp_zero::practice_exercise::score_variant> variants{};
};
struct practice_lesson_group {
std::string id{};
std::string title{};
std::vector<vamp_zero::practice_exercise> exercises{};
};
struct practice_type_group {
std::string id{};
std::string title{};
std::vector<vamp_zero::practice_lesson_group> lesson_groups{};
};
struct practice_library {
std::vector<vamp_zero::practice_exercise> exercises{};
std::vector<vamp_zero::practice_type_group> types{};
};
enum class app_mode {
MAIN_MENU,
PERFORMANCE_SONG_MENU,
PERFORMANCE_PART_MENU,
PERFORMANCE_SCORE,
PRACTICE_TYPE_MENU,
PRACTICE_LESSON_MENU,
PRACTICE_EXERCISE_MENU,
PRACTICE_KEY_MENU,
PRACTICE_SCORE,
};
struct app_state {
vamp_zero::library_state performance{};
vamp_zero::practice_library practice{};
vamp_zero::app_mode mode{vamp_zero::app_mode::MAIN_MENU};
std::size_t selected_main_menu_index{};
std::size_t selected_song_index{};
std::size_t selected_part_index{};
std::size_t selected_practice_type_index{};
std::size_t selected_practice_lesson_index{};
std::size_t selected_practice_exercise_index{};
std::size_t selected_practice_key_index{};
std::string active_part_id{};
std::string active_practice_id{};
std::size_t page_index{};
std::uint64_t next_count{};
std::uint64_t previous_count{};
std::uint64_t select_count{};
std::uint64_t heartbeat_count{};
std::string last_command{"startup"};
std::bool_t pico_connected{false};
};
auto to_string(vamp_zero::hardware_mode value) -> std::string;
auto to_string(vamp_zero::app_mode value) -> std::string;
auto practice_key_names() -> std::vector<std::string_view> const&;
auto practice_type_supports_key_selection(std::string_view practice_type_id) -> std::bool_t;
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <expected>
#include <cstdint>
#include <memory>
#include <mutex>
#include <string>
#include <boost/asio/any_io_executor.hpp>
#include <luma.hpp>
#include <modulus.hpp>
#include <vamp_zero/config.hpp>
#include <vamp_zero/types.hpp>
namespace vamp_zero {
struct ui_state {
vamp_zero::app_state app{};
std::string ap_ssid{};
std::string zero_ip{};
std::uint16_t port{8080};
};
class zero_ui {
public:
zero_ui(boost::asio::any_io_executor executor, luma::application_config config);
auto run() -> std::expected<void, modulus::error>;
auto stop() -> void;
auto publish(vamp_zero::ui_state state) -> std::expected<void, modulus::error>;
auto snapshot() const -> vamp_zero::ui_state;
private:
auto make_root(vamp_zero::ui_state const& state) -> std::expected<std::unique_ptr<luma::control>, modulus::error>;
boost::asio::any_io_executor executor_;
luma::application application_;
mutable std::mutex mutex_{};
vamp_zero::ui_state state_{};
};
auto make_ui_state(vamp_zero::config const& config, vamp_zero::app_state app) -> vamp_zero::ui_state;
}