+13
-184
@@ -20,11 +20,10 @@
|
||||
namespace {
|
||||
|
||||
constexpr auto main_menu_performance = std::size_t{0};
|
||||
constexpr auto main_menu_practice = std::size_t{1};
|
||||
constexpr auto main_menu_playback = std::size_t{2};
|
||||
constexpr auto main_menu_metronome = std::size_t{3};
|
||||
constexpr auto main_menu_tempo = std::size_t{4};
|
||||
constexpr auto main_menu_count = std::size_t{5};
|
||||
constexpr auto main_menu_playback = std::size_t{1};
|
||||
constexpr auto main_menu_metronome = std::size_t{2};
|
||||
constexpr auto main_menu_tempo = std::size_t{3};
|
||||
constexpr auto main_menu_count = std::size_t{4};
|
||||
|
||||
auto wrap_next(std::size_t value, std::size_t count) -> std::size_t {
|
||||
if (count == 0U) {
|
||||
@@ -71,48 +70,27 @@ auto clamp_state(vamp_zero::app_state state) -> vamp_zero::app_state {
|
||||
}
|
||||
state.audio = clamp_audio_state(state.audio);
|
||||
state.selected_main_menu_index = std::min(state.selected_main_menu_index, main_menu_count - 1U);
|
||||
state.selected_song_index = std::min(state.selected_song_index, menu_row_count(state.catalog->performance.groups.size()) - 1U);
|
||||
state.selected_song_index = std::min(state.selected_song_index, menu_row_count(state.catalog->groups.size()) - 1U);
|
||||
if (auto const *group = selected_group(state); group != nullptr) {
|
||||
state.selected_part_index = std::min(state.selected_part_index, menu_row_count(group->parts.size()) - 1U);
|
||||
} else {
|
||||
state.selected_part_index = 0U;
|
||||
}
|
||||
state.selected_practice_exercise_index = std::min(state.selected_practice_exercise_index, state.catalog->practice.exercises.size());
|
||||
state.selected_practice_part_index = std::min(state.selected_practice_part_index, practice_part_row_count(state) - 1U);
|
||||
if (state.mode == vamp_zero::app_mode::PERFORMANCE_PART_MENU && selected_group(state) == nullptr) {
|
||||
state.mode = vamp_zero::app_mode::PERFORMANCE_SONG_MENU;
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_PART_MENU) {
|
||||
auto const *exercise = selected_practice_exercise(state);
|
||||
if (exercise == nullptr || exercise->parts.empty()) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.selected_practice_part_index = 0U;
|
||||
}
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PERFORMANCE_SCORE && active_part(state) == nullptr) {
|
||||
state.mode = selected_group(state) == nullptr ? vamp_zero::app_mode::PERFORMANCE_SONG_MENU
|
||||
: vamp_zero::app_mode::PERFORMANCE_PART_MENU;
|
||||
state.active_part_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (state.mode == vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
auto const *exercise = active_practice(state);
|
||||
if (exercise == nullptr) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (selected_practice_part(state, *exercise) == nullptr) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_PART_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
}
|
||||
}
|
||||
if (state.mode != vamp_zero::app_mode::MAIN_MENU) {
|
||||
state.audio.tempo_editing = false;
|
||||
}
|
||||
if (auto pages = active_pages(state); pages != 0U) {
|
||||
state.page_index = std::min(state.page_index, pages - 1U);
|
||||
} else if (state.mode != vamp_zero::app_mode::PERFORMANCE_SCORE &&
|
||||
state.mode != vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
} else if (state.mode != vamp_zero::app_mode::PERFORMANCE_SCORE) {
|
||||
state.page_index = 0;
|
||||
}
|
||||
return state;
|
||||
@@ -154,26 +132,12 @@ auto part_json(vamp_zero::library_part const &part) -> boost::json::object {
|
||||
return result;
|
||||
}
|
||||
|
||||
auto exercise_json(vamp_zero::practice_exercise const &exercise) -> boost::json::object {
|
||||
auto parts = boost::json::array{};
|
||||
for (auto const &part : exercise.parts) {
|
||||
parts.push_back(part_json(part));
|
||||
}
|
||||
auto result = boost::json::object{};
|
||||
result["id"] = exercise.id;
|
||||
result["title"] = exercise.title;
|
||||
result["composer"] = exercise.composer;
|
||||
result["part_count"] = static_cast<std::uint64_t>(exercise.parts.size());
|
||||
result["parts"] = std::move(parts);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto performance_json(vamp_zero::app_state const &state) -> boost::json::object {
|
||||
auto groups = boost::json::array{};
|
||||
for (auto const &group : state.catalog->performance.groups) {
|
||||
for (auto const &group : state.catalog->groups) {
|
||||
auto parts = boost::json::array{};
|
||||
for (auto const &part : group.parts) {
|
||||
parts.push_back(part_json(state.catalog->performance.parts[part]));
|
||||
parts.push_back(part_json(state.catalog->parts[part]));
|
||||
}
|
||||
auto item = boost::json::object{};
|
||||
item["title"] = group.title;
|
||||
@@ -182,34 +146,12 @@ auto performance_json(vamp_zero::app_state const &state) -> boost::json::object
|
||||
groups.push_back(std::move(item));
|
||||
}
|
||||
auto library = boost::json::object{};
|
||||
library["song_count"] = static_cast<std::uint64_t>(state.catalog->performance.groups.size());
|
||||
library["part_count"] = static_cast<std::uint64_t>(state.catalog->performance.parts.size());
|
||||
library["song_count"] = static_cast<std::uint64_t>(state.catalog->groups.size());
|
||||
library["part_count"] = static_cast<std::uint64_t>(state.catalog->parts.size());
|
||||
library["groups"] = std::move(groups);
|
||||
return library;
|
||||
}
|
||||
|
||||
auto practice_json(vamp_zero::app_state const &state) -> boost::json::object {
|
||||
auto exercises = boost::json::array{};
|
||||
for (auto const &exercise : state.catalog->practice.exercises) {
|
||||
exercises.push_back(exercise_json(exercise));
|
||||
}
|
||||
auto selection = boost::json::object{};
|
||||
selection["exercise_row_index"] = static_cast<std::uint64_t>(state.selected_practice_exercise_index);
|
||||
selection["part_row_index"] = static_cast<std::uint64_t>(state.selected_practice_part_index);
|
||||
if (auto const *exercise = selected_practice_exercise(state); exercise != nullptr) {
|
||||
selection["exercise"] = exercise_json(*exercise);
|
||||
auto practice_part = selected_practice_part(state, *exercise);
|
||||
if (practice_part != nullptr) {
|
||||
selection["part"] = part_json(*practice_part);
|
||||
}
|
||||
}
|
||||
auto practice = boost::json::object{};
|
||||
practice["exercise_count"] = static_cast<std::uint64_t>(state.catalog->practice.exercises.size());
|
||||
practice["exercises"] = std::move(exercises);
|
||||
practice["selection"] = std::move(selection);
|
||||
return practice;
|
||||
}
|
||||
|
||||
auto sanitize_line_value(std::string value) -> std::string {
|
||||
for (auto &ch : value) {
|
||||
if (ch == '\r' || ch == '\n') {
|
||||
@@ -251,12 +193,6 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
state.selected_part_index = 0;
|
||||
state.active_part_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (state.selected_main_menu_index == main_menu_practice) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.selected_practice_exercise_index = 0;
|
||||
state.selected_practice_part_index = 0;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (state.selected_main_menu_index == main_menu_playback) {
|
||||
state.audio.playback_enabled = !state.audio.playback_enabled;
|
||||
} else if (state.selected_main_menu_index == main_menu_metronome) {
|
||||
@@ -267,11 +203,11 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
return clamp_state(std::move(state));
|
||||
case vamp_zero::app_mode::PERFORMANCE_SONG_MENU:
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
state.selected_song_index = wrap_next(state.selected_song_index, menu_row_count(state.catalog->performance.groups.size()));
|
||||
state.selected_song_index = wrap_next(state.selected_song_index, menu_row_count(state.catalog->groups.size()));
|
||||
state.selected_part_index = 0;
|
||||
} else if (command == vamp_protocol::page_command::PREVIOUS) {
|
||||
state.selected_song_index =
|
||||
wrap_previous(state.selected_song_index, menu_row_count(state.catalog->performance.groups.size()));
|
||||
wrap_previous(state.selected_song_index, menu_row_count(state.catalog->groups.size()));
|
||||
state.selected_part_index = 0;
|
||||
} else if (state.selected_song_index == 0U) {
|
||||
state.mode = vamp_zero::app_mode::MAIN_MENU;
|
||||
@@ -292,7 +228,6 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
state.page_index = 0;
|
||||
} else if (auto const *part = selected_part(state); part != nullptr) {
|
||||
state.active_part_id = part->id;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
state.mode = vamp_zero::app_mode::PERFORMANCE_SCORE;
|
||||
++state.score_session;
|
||||
@@ -313,63 +248,6 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
}
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
case vamp_zero::app_mode::PRACTICE_EXERCISE_MENU:
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
state.selected_practice_exercise_index = wrap_next(state.selected_practice_exercise_index, menu_row_count(state.catalog->practice.exercises.size()));
|
||||
state.selected_practice_part_index = 0;
|
||||
} else if (command == vamp_protocol::page_command::PREVIOUS) {
|
||||
state.selected_practice_exercise_index = wrap_previous(state.selected_practice_exercise_index, menu_row_count(state.catalog->practice.exercises.size()));
|
||||
state.selected_practice_part_index = 0;
|
||||
} else if (state.selected_practice_exercise_index == 0U) {
|
||||
state.mode = vamp_zero::app_mode::MAIN_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (selected_practice_exercise(state) != nullptr) {
|
||||
state.active_part_id.clear();
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_PART_MENU;
|
||||
state.selected_practice_part_index = 0;
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
case vamp_zero::app_mode::PRACTICE_PART_MENU:
|
||||
if (auto const *exercise = selected_practice_exercise(state);
|
||||
exercise != nullptr) {
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
state.selected_practice_part_index =
|
||||
wrap_next(state.selected_practice_part_index, menu_row_count(exercise->parts.size()));
|
||||
} else if (command == vamp_protocol::page_command::PREVIOUS) {
|
||||
state.selected_practice_part_index =
|
||||
wrap_previous(state.selected_practice_part_index, menu_row_count(exercise->parts.size()));
|
||||
} else if (state.selected_practice_part_index == 0U) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (selected_practice_part(state, *exercise) != nullptr) {
|
||||
state.active_practice_id = exercise->id;
|
||||
state.active_part_id.clear();
|
||||
state.page_index = 0;
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_SCORE;
|
||||
++state.score_session;
|
||||
state.audio.playback_error.clear();
|
||||
}
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
case vamp_zero::app_mode::PRACTICE_SCORE:
|
||||
if (auto const *exercise = active_practice(state); exercise != nullptr) {
|
||||
auto const *practice_part = selected_practice_part(state, *exercise);
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
auto pages = practice_part == nullptr ? 0U : practice_part->total_pages;
|
||||
state.page_index = std::min(state.page_index + 1U, pages == 0U ? 0U : pages - 1U);
|
||||
} else if (command == vamp_protocol::page_command::PREVIOUS) {
|
||||
state.page_index = state.page_index == 0U ? 0U : state.page_index - 1U;
|
||||
} else {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_PART_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
}
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
}
|
||||
return clamp_state(std::move(state));
|
||||
}
|
||||
@@ -396,19 +274,6 @@ auto vamp_zero::app_status_json(vamp_zero::app_state const &state) -> boost::jso
|
||||
active["page_number"] = static_cast<std::uint64_t>(state.page_index + 1U);
|
||||
active["page_total"] = static_cast<std::uint64_t>(part->total_pages);
|
||||
}
|
||||
} else if (state.mode == vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
if (auto const *exercise = active_practice(state); exercise != nullptr) {
|
||||
auto const *practice_part = selected_practice_part(state, *exercise);
|
||||
active["selected"] = true;
|
||||
active["kind"] = "practice";
|
||||
active["exercise"] = exercise_json(*exercise);
|
||||
if (practice_part != nullptr) {
|
||||
active["part"] = part_json(*practice_part);
|
||||
}
|
||||
active["page_index"] = static_cast<std::uint64_t>(state.page_index);
|
||||
active["page_number"] = static_cast<std::uint64_t>(state.page_index + 1U);
|
||||
active["page_total"] = static_cast<std::uint64_t>(practice_part == nullptr ? 0U : practice_part->total_pages);
|
||||
}
|
||||
}
|
||||
if (active.empty()) {
|
||||
active["selected"] = false;
|
||||
@@ -424,7 +289,6 @@ auto vamp_zero::app_status_json(vamp_zero::app_state const &state) -> boost::jso
|
||||
root["mode"] = vamp_zero::to_string(state.mode);
|
||||
root["library"] = performance;
|
||||
root["performance"] = std::move(performance);
|
||||
root["practice"] = practice_json(state);
|
||||
root["selection"] = std::move(selection);
|
||||
root["active"] = std::move(active);
|
||||
root["audio"] = audio_json(state);
|
||||
@@ -449,16 +313,6 @@ auto vamp_zero::remote_display_text(vamp_zero::app_state const &state) -> std::s
|
||||
page = state.page_index + 1U;
|
||||
pages = selected->total_pages;
|
||||
}
|
||||
} else if (state.mode == vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
if (auto const *selected = active_practice(state); selected != nullptr) {
|
||||
auto const *practice_part = selected_practice_part(state, *selected);
|
||||
active = true;
|
||||
title = selected->title;
|
||||
part = practice_part == nullptr ? std::string{} : practice_part->part;
|
||||
title_image = practice_part == nullptr ? std::string{} : practice_part->title_image;
|
||||
page = state.page_index + 1U;
|
||||
pages = practice_part == nullptr ? 0U : practice_part->total_pages;
|
||||
}
|
||||
}
|
||||
auto output = std::ostringstream{};
|
||||
output << "mode=" << vamp_zero::to_string(state.mode) << "\n";
|
||||
@@ -494,25 +348,13 @@ auto vamp_zero::validate_app_state(vamp_zero::app_state const &state) -> std::ex
|
||||
if (state.audio.tempo_editing && state.mode != vamp_zero::app_mode::MAIN_MENU) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "tempo edit mode requires the main menu"));
|
||||
}
|
||||
if (state.selected_song_index >= menu_row_count(state.catalog->performance.groups.size())) {
|
||||
if (state.selected_song_index >= menu_row_count(state.catalog->groups.size())) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected performance song row is out of range"));
|
||||
}
|
||||
if (auto const *group = selected_group(state);
|
||||
group != nullptr && state.selected_part_index >= menu_row_count(group->parts.size())) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected performance part row is out of range"));
|
||||
}
|
||||
if (state.selected_practice_exercise_index >= menu_row_count(state.catalog->practice.exercises.size())) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected practice exercise row is out of range"));
|
||||
}
|
||||
if (state.selected_practice_part_index >= practice_part_row_count(state)) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected practice part row is out of range"));
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_PART_MENU) {
|
||||
auto const *exercise = selected_practice_exercise(state);
|
||||
if (exercise == nullptr || exercise->parts.empty()) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice part mode requires an exercise with parts"));
|
||||
}
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PERFORMANCE_SCORE) {
|
||||
auto const *part = active_part(state);
|
||||
if (part == nullptr) {
|
||||
@@ -522,18 +364,5 @@ auto vamp_zero::validate_app_state(vamp_zero::app_state const &state) -> std::ex
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "performance score page index is out of range"));
|
||||
}
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
auto const *exercise = active_practice(state);
|
||||
if (exercise == nullptr) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice score mode requires an active exercise"));
|
||||
}
|
||||
auto const *practice_part = selected_practice_part(state, *exercise);
|
||||
if (practice_part == nullptr) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice score mode requires a selected generated part"));
|
||||
}
|
||||
if (practice_part->total_pages == 0U || state.page_index >= practice_part->total_pages) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice score page index is out of range"));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user