@@ -78,15 +78,15 @@ auto clamp_state(vamp_zero::app_state state) -> vamp_zero::app_state {
|
||||
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_key_index = std::min(state.selected_practice_key_index, practice_key_row_count(state) - 1U);
|
||||
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_KEY_MENU) {
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_PART_MENU) {
|
||||
auto const *exercise = selected_practice_exercise(state);
|
||||
if (exercise == nullptr || exercise->variants.empty()) {
|
||||
if (exercise == nullptr || exercise->parts.empty()) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.selected_practice_key_index = 0U;
|
||||
state.selected_practice_part_index = 0U;
|
||||
}
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PERFORMANCE_SCORE && active_part(state) == nullptr) {
|
||||
@@ -100,8 +100,8 @@ auto clamp_state(vamp_zero::app_state state) -> vamp_zero::app_state {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_EXERCISE_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
} else if (selected_practice_variant(state, *exercise) == nullptr) {
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_KEY_MENU;
|
||||
} 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;
|
||||
}
|
||||
@@ -155,30 +155,16 @@ auto part_json(vamp_zero::library_part const &part) -> boost::json::object {
|
||||
}
|
||||
|
||||
auto exercise_json(vamp_zero::practice_exercise const &exercise) -> boost::json::object {
|
||||
auto variants = boost::json::array{};
|
||||
for (auto const &variant : exercise.variants) {
|
||||
auto item = boost::json::object{};
|
||||
item["id"] = variant.id;
|
||||
item["key_signature"] = variant.key_signature;
|
||||
item["source_path"] = variant.source_path;
|
||||
item["measures"] = static_cast<std::uint64_t>(variant.measure_count);
|
||||
item["pages"] = static_cast<std::uint64_t>(variant.total_pages);
|
||||
variants.push_back(std::move(item));
|
||||
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["authored_key_signature"] = exercise.authored_key_signature;
|
||||
if (!exercise.variants.empty()) {
|
||||
auto const &primary = exercise.variants.front();
|
||||
result["key_signature"] = primary.key_signature;
|
||||
result["source_path"] = primary.source_path;
|
||||
result["measures"] = static_cast<std::uint64_t>(primary.measure_count);
|
||||
result["pages"] = static_cast<std::uint64_t>(primary.total_pages);
|
||||
}
|
||||
result["variant_count"] = static_cast<std::uint64_t>(exercise.variants.size());
|
||||
result["variants"] = std::move(variants);
|
||||
result["part_count"] = static_cast<std::uint64_t>(exercise.parts.size());
|
||||
result["parts"] = std::move(parts);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -207,36 +193,19 @@ auto practice_json(vamp_zero::app_state const &state) -> boost::json::object {
|
||||
for (auto const &exercise : state.catalog->practice.exercises) {
|
||||
exercises.push_back(exercise_json(exercise));
|
||||
}
|
||||
auto keys = boost::json::array{};
|
||||
for (auto key : vamp_zero::practice_key_names()) {
|
||||
keys.push_back(boost::json::value{std::string{key}});
|
||||
}
|
||||
auto selection = boost::json::object{};
|
||||
selection["exercise_row_index"] = static_cast<std::uint64_t>(state.selected_practice_exercise_index);
|
||||
selection["key_row_index"] = static_cast<std::uint64_t>(state.selected_practice_key_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 variant = selected_practice_variant(state, *exercise);
|
||||
if (variant != nullptr) {
|
||||
auto item = boost::json::object{};
|
||||
item["id"] = variant->id;
|
||||
item["key_signature"] = variant->key_signature;
|
||||
item["source_path"] = variant->source_path;
|
||||
item["measures"] = static_cast<std::uint64_t>(variant->measure_count);
|
||||
item["pages"] = static_cast<std::uint64_t>(variant->total_pages);
|
||||
selection["variant"] = std::move(item);
|
||||
}
|
||||
}
|
||||
if (auto const *exercise = selected_practice_exercise(state); exercise != nullptr) {
|
||||
if (auto key = selected_practice_key(state, *exercise)) {
|
||||
selection["key"] = std::string{*key};
|
||||
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["key_count"] = static_cast<std::uint64_t>(vamp_zero::practice_key_names().size());
|
||||
practice["keys"] = std::move(keys);
|
||||
practice["selection"] = std::move(selection);
|
||||
return practice;
|
||||
}
|
||||
@@ -285,7 +254,7 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
} 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_key_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) {
|
||||
@@ -347,10 +316,10 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
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_key_index = 0;
|
||||
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_key_index = 0;
|
||||
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();
|
||||
@@ -359,24 +328,24 @@ auto vamp_zero::apply_app_command(vamp_zero::app_state state, vamp_protocol::pag
|
||||
state.active_part_id.clear();
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_KEY_MENU;
|
||||
state.selected_practice_key_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_KEY_MENU:
|
||||
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_key_index =
|
||||
wrap_next(state.selected_practice_key_index, menu_row_count(exercise->variants.size()));
|
||||
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_key_index =
|
||||
wrap_previous(state.selected_practice_key_index, menu_row_count(exercise->variants.size()));
|
||||
} else if (state.selected_practice_key_index == 0U) {
|
||||
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_variant(state, *exercise) != nullptr) {
|
||||
} else if (selected_practice_part(state, *exercise) != nullptr) {
|
||||
state.active_practice_id = exercise->id;
|
||||
state.active_part_id.clear();
|
||||
state.page_index = 0;
|
||||
@@ -388,14 +357,14 @@ 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_SCORE:
|
||||
if (auto const *exercise = active_practice(state); exercise != nullptr) {
|
||||
auto const *variant = selected_practice_variant(state, *exercise);
|
||||
auto const *practice_part = selected_practice_part(state, *exercise);
|
||||
if (command == vamp_protocol::page_command::NEXT) {
|
||||
auto pages = variant == nullptr ? 0U : variant->total_pages;
|
||||
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_KEY_MENU;
|
||||
state.mode = vamp_zero::app_mode::PRACTICE_PART_MENU;
|
||||
state.active_practice_id.clear();
|
||||
state.page_index = 0;
|
||||
}
|
||||
@@ -429,14 +398,16 @@ auto vamp_zero::app_status_json(vamp_zero::app_state const &state) -> boost::jso
|
||||
}
|
||||
} else if (state.mode == vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
if (auto const *exercise = active_practice(state); exercise != nullptr) {
|
||||
auto const *variant = selected_practice_variant(state, *exercise);
|
||||
auto const *practice_part = selected_practice_part(state, *exercise);
|
||||
active["selected"] = true;
|
||||
active["kind"] = "practice";
|
||||
active["exercise"] = exercise_json(*exercise);
|
||||
active["key"] = effective_practice_key(state, *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>(variant == nullptr ? 0U : variant->total_pages);
|
||||
active["page_total"] = static_cast<std::uint64_t>(practice_part == nullptr ? 0U : practice_part->total_pages);
|
||||
}
|
||||
}
|
||||
if (active.empty()) {
|
||||
@@ -478,12 +449,12 @@ auto vamp_zero::remote_display_text(vamp_zero::app_state const &state) -> std::s
|
||||
}
|
||||
} else if (state.mode == vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
if (auto const *selected = active_practice(state); selected != nullptr) {
|
||||
auto const *variant = selected_practice_variant(state, *selected);
|
||||
auto const *practice_part = selected_practice_part(state, *selected);
|
||||
active = true;
|
||||
title = selected->title;
|
||||
part = "Key: " + effective_practice_key(state, *selected);
|
||||
part = practice_part == nullptr ? std::string{} : practice_part->part;
|
||||
page = state.page_index + 1U;
|
||||
pages = variant == nullptr ? 0U : variant->total_pages;
|
||||
pages = practice_part == nullptr ? 0U : practice_part->total_pages;
|
||||
}
|
||||
}
|
||||
auto output = std::ostringstream{};
|
||||
@@ -529,13 +500,13 @@ auto vamp_zero::validate_app_state(vamp_zero::app_state const &state) -> std::ex
|
||||
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_key_index >= practice_key_row_count(state)) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "selected practice key 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_KEY_MENU) {
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_PART_MENU) {
|
||||
auto const *exercise = selected_practice_exercise(state);
|
||||
if (exercise == nullptr || exercise->variants.empty()) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice key mode requires an exercise with key variants"));
|
||||
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) {
|
||||
@@ -552,11 +523,11 @@ auto vamp_zero::validate_app_state(vamp_zero::app_state const &state) -> std::ex
|
||||
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 *variant = selected_practice_variant(state, *exercise);
|
||||
if (variant == nullptr) {
|
||||
return std::unexpected(vamp_zero::make_error(vamp_zero::error_code::INVALID_ARGUMENT, "practice score mode requires a selected generated variant"));
|
||||
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 (variant->total_pages == 0U || state.page_index >= variant->total_pages) {
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user