diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-11-06 22:38:36 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-11-06 22:38:36 -0500 |
| commit | f65db3c166ee1f41a7a33b0c19296f46babb09a5 (patch) | |
| tree | b98dcb6c0456f1daead3e6c15b617d18e552a1e5 | |
| parent | 6ca4d7a6b6c896cfcba0b3dfe02bf135b5c8ead7 (diff) | |
pke-at: chkpt: level-import
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | src/level-import.cpp | 424 | ||||
| -rw-r--r-- | src/level-import.hpp | 11 | ||||
| -rw-r--r-- | src/level-main.cpp | 68 | ||||
| -rw-r--r-- | src/pke-at-data-interface.hpp | 4 | ||||
| -rw-r--r-- | src/pke-at-data-planning-center.hpp | 6 | ||||
| -rw-r--r-- | src/pke-at-data-stub.cpp | 21 | ||||
| -rw-r--r-- | src/pke-at-data-stub.hpp | 4 | ||||
| -rw-r--r-- | src/pke-at-setlist-types.cpp | 23 | ||||
| -rw-r--r-- | src/pke-at-setlist-types.hpp | 9 | ||||
| -rw-r--r-- | src/pke-at-settings.hpp | 1 | ||||
| -rw-r--r-- | src/pke-at.cpp | 20 |
13 files changed, 560 insertions, 35 deletions
@@ -91,6 +91,7 @@ obj/%.o : tests/%.cpp | prepare $(cxx-command) bin/pke-at: ## Builds the pke-at executable +bin/pke-at: obj/level-import.o bin/pke-at: obj/level-init.o bin/pke-at: obj/level-main.o bin/pke-at: obj/main.o @@ -98,6 +99,7 @@ bin/pke-at: obj/pke-at-common.o bin/pke-at: obj/pke-at-data-stub.o bin/pke-at: obj/pke-at-data-parser.o bin/pke-at: obj/pke-at-settings.o +bin/pke-at: obj/pke-at-setlist-types.o bin/pke-at: obj/pke-at-storage-sql.o bin/pke-at: obj/pke-at.o $(CXX) -v -std=c++23 $(BUILD_MODE_FLAGS) $(INCS) -Wl,--whole-archive $^ $(LDFLAGS) -Wl,--no-whole-archive $(CXXFLAGS) -o $@ @@ -20,7 +20,7 @@ GLSLC = /usr/bin/glslc # libpipewire-0.3 \ # libspa-0.2 \ -USED_STATIC_LIBS = pke \ +USED_STATIC_LIBS = pke-dbg \ sqlite3 \ nlohmann_json \ diff --git a/src/level-import.cpp b/src/level-import.cpp new file mode 100644 index 0000000..63fe66b --- /dev/null +++ b/src/level-import.cpp @@ -0,0 +1,424 @@ + +#include "level-main.hpp" +#include "pke-at-data-interface-types.hpp" +#include "pke-at-data-interface.hpp" +#include "pke-at-setlist-types.hpp" +#include "pke-at-settings.hpp" +#include "pke-at-storage-interface.hpp" + +#include "level-import.hpp" + +#include <chrono> +#include <future> +#include <pke/pke.hpp> + +typedef int pke_level_import_state; + +static const pke_level_import_state state_none = 0; +static const pke_level_import_state state_get_service_types = 1; +static const pke_level_import_state state_display_service_types = 2; +static const pke_level_import_state state_wait_service_types = 3; +static const pke_level_import_state state_err_service_types = 4; +static const pke_level_import_state state_get_upcoming_plans = 5; +static const pke_level_import_state state_display_upcoming_plans = 6; +static const pke_level_import_state state_wait_upcoming_plans = 7; +static const pke_level_import_state state_err_upcoming_plans = 8; +static const pke_level_import_state state_get_plan_items = 9; +static const pke_level_import_state state_err_plan_items = 10; +static const pke_level_import_state state_display_summary = 11; +static const pke_level_import_state state_wait_summary = 12; + +void pke_at_level_import_recalc_ui(void*,void*,void*); +void pke_at_level_import_service_type_clicked(void *vbox, void *data, void*); +void pke_at_level_import_upcoming_plan_clicked(void *vbox, void *data, void*); +void pke_at_level_import_back_clicked(void*,void*,void*); +void pke_at_level_import_exit_clicked(void*,void*,void*); +void pke_at_level_import_import_clicked(void*,void*,void*); +pke_ui_box *pke_at_level_import_build_ui_list_item(pke_ui_box *parent_box, pk_cstr &&str, pk_ev_cb_fn fn, void *item_ptr, PKE_UI_BOX_TYPE box_type); +void pke_at_level_import_build_ui_service_types(); +void pke_at_level_import_build_ui_upcoming_plans(); +void pke_at_level_import_build_ui_setlist_import_details(); + +static struct pke_level_import_master { + pke_level *level = nullptr; + pke_level_import_state state = state_none; + struct pke_level_import_master_ui { + pke_ui_box *root_box; + pke_ui_box *root_bottom_bar; + pke_ui_box *root_setlist_details; + pke_ui_box *root_setlist_items; + pke_ui_box *btn_exit; + pke_ui_box *btn_back; + pke_ui_box *btn_import; + } ui; + struct pke_level_import_data { + FPADIRT(pk_arr_t<di_service_type>) future_service_types; + pk_arr_t<di_service_type> service_types; + di_service_type *selected_service_type; + FPADIRT(pk_arr_t<di_plan>) future_upcoming_plans; + pk_arr_t<di_plan> plans; + di_plan *selected_plan; + FPADIRT(pk_arr_t<di_plan_item>) future_plan_items; + pk_arr_t<di_plan_item> plan_items; + } data; +} lvl_mstr; + +pke_level *pke_at_level_import_create() { + lvl_mstr.level = pke_level_create("import", pk_uuid_zed, pk_uuid_zed); + lvl_mstr.level->pke_cb_spinup.func = pke_at_level_import_init; + lvl_mstr.level->pke_cb_tick.func = (void(*)())pke_at_level_import_tick; + lvl_mstr.level->pke_cb_teardown.func = pke_at_level_import_teardown; + return lvl_mstr.level; +} + +void pke_at_level_import_recalc_ui(void*a=nullptr,void*b=nullptr,void*c=nullptr) { + (void)a; (void)b; (void)c; + pke_ui_box *root = nullptr; + root = lvl_mstr.ui.root_box; + if (root != nullptr) { + root->min_size.x = 0; + root->min_size.y = 0; + root->max_size.x = Extent.width - 8; + root->max_size.y = Extent.height - 104; + root->pos_top_left.x = 4; + root->pos_top_left.y = 0; + } + root = lvl_mstr.ui.root_bottom_bar; + if (root != nullptr) { + root->min_size.x = Extent.width; + root->min_size.y = 100; + root->max_size.x = Extent.width; + root->max_size.y = 100; + root->pos_top_left.x = 0; + root->pos_top_left.y = Extent.height - 104; + } + root = lvl_mstr.ui.root_setlist_details; + if (root != nullptr) { + root->min_size.x = 500; + root->min_size.y = Extent.height - 116; + root->max_size.x = 500; + root->max_size.y = Extent.height - 116; + root->pos_top_left.x = 6; + root->pos_top_left.y = 6; + } + root = lvl_mstr.ui.root_setlist_items; + if (root != nullptr) { + root->min_size.x = Extent.width - 518; + root->min_size.y = Extent.height - 116; + root->max_size.x = Extent.width - 518; + root->max_size.y = Extent.height - 116; + root->pos_top_left.x = 512; + root->pos_top_left.y = 6; + } +} + +void pke_at_level_import_service_type_clicked(void *vbox, void *data, void *) { + fprintf(stdout, "[%s] pke_at_level_import_service_type_clicked : %lu\n", __FILE__, time(NULL)); + (void)vbox; + di_service_type *service_type = *reinterpret_cast<di_service_type**>(data); + lvl_mstr.data.future_upcoming_plans = g_at.data->get_plans_upcoming_from_service_type(service_type); + lvl_mstr.data.selected_service_type = service_type; + lvl_mstr.state = state_get_upcoming_plans; +} + +void pke_at_level_import_upcoming_plan_clicked(void *vbox, void *data, void*) { + (void)vbox; + di_plan *plan = *reinterpret_cast<di_plan**>(data); + lvl_mstr.data.future_plan_items = g_at.data->get_plan_items(plan); + lvl_mstr.data.selected_plan = plan; + lvl_mstr.state = state_get_plan_items; +} + +void pke_at_level_import_back_clicked(void*,void*,void*) { + switch (lvl_mstr.state) { + case state_wait_service_types: + pkeSettings.rt.nextLevel = pke_at_level_main_create(); + break; + case state_wait_upcoming_plans: + lvl_mstr.data.selected_service_type = nullptr; + pk_arr_reset(&lvl_mstr.data.plans); + lvl_mstr.state = state_display_service_types; + break; + case state_wait_summary: + lvl_mstr.data.selected_plan = nullptr; + pk_arr_reset(&lvl_mstr.data.plan_items); + lvl_mstr.ui.btn_import->flags |= PKE_UI_BOX_FLAG_VISIBILITY_DISABLED; + lvl_mstr.ui.root_setlist_items->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE; + lvl_mstr.ui.root_setlist_details->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE; + lvl_mstr.state = state_display_upcoming_plans; + break; + default: + fprintf(stderr, "[%s] pke_at_level_import_back_clicked unhandled state: %i", __FILE__, lvl_mstr.state); + break; + } +} + +void pke_at_level_import_exit_clicked(void*,void*,void*) { + pkeSettings.rt.nextLevel = pke_at_level_main_create(); +} + +void pke_at_level_import_import_clicked(void*,void*,void*) { + uint32_t u; + + pke_at_setlist_details setlist_details; + setlist_details.uuid = pk_uuid_new_v7(); + setlist_details.title = lvl_mstr.data.selected_plan->details.title; + g_at.storage->pke_at_storage_interface_setlist_upsert(setlist_details); + + for (u = 0; u < lvl_mstr.data.plans.next; ++u) { + di_plan_item *plan_item = &lvl_mstr.data.plan_items[u]; + pke_at_song_details song_details{}; + song_details.uuid = pk_uuid_new_v7(); + song_details.key = plan_item->details.key; + song_details.ccli = plan_item->song.details.ccli; + song_details.title = plan_item->song.details.title; + song_details.arrangement = plan_item->arrangement.details.title; + song_details.bpm = plan_item->arrangement.details.beats_per_minute; + g_at.storage->pke_at_storage_interface_song_upsert(song_details); + pke_at_setlist_song_details setlist_song_details{}; + setlist_song_details.setlist_uuid = setlist_details.uuid; + setlist_song_details.song_uuid = song_details.uuid; + g_at.storage->pke_at_storage_interface_setlist_song_upsert(setlist_song_details); + } + + // EXIT LEVEL +} + +pke_ui_box *pke_at_level_import_build_ui_list_item(pke_ui_box *parent_box, pk_cstr &&str, pk_ev_cb_fn fn = nullptr, void *item_ptr = nullptr, PKE_UI_BOX_TYPE box_type = PKE_UI_BOX_TYPE_BUTTON_TEXT) { + FontRenderSettings frs{}; + pke_component_event *ev; + frs.char_scale = 32; + frs.surface_area_type_flags = FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_BOTH; + frs.color_background = glm::vec4(0,0,0,1); + frs.color_foreground = glm::vec4(1,1,1,1); + frs.flags = FONT_RENDER_FLAG_NONE; + pke_ui_box *bx = pke_ui_box_new_child(parent_box, box_type); + bx->flex_weight = 1; + bx->flags |= PKE_UI_BOX_FLAG_POSITION_TYPE_FLEX; + bx->min_size.x = 0; + bx->min_size.y = 0; + bx->max_size.x = 8000; + bx->max_size.y = 8000; + bx->pos_top_left.x = 0; + bx->pos_top_left.y = 0; + if (box_type == PKE_UI_BOX_TYPE_TEXT) { + bx->type_data->text.font_type_render = FontType_AddStringRender(FontTypeIndex{0}, std::move(str), &frs); + } + if (box_type == PKE_UI_BOX_TYPE_BUTTON_TEXT) { + ev = ECS_GetEv(bx->type_data->button_text.pke_event_handle); + pk_ev_register_cb(ev->ev_mgr_id, ev->ev_id, fn, item_ptr); + fprintf(stdout, "[%s] pke_at_level_import_build_ui_list_item box: %p, ev_id: %lu, ev_handle %u:%u\n", __FILE__, (void *)bx, ev->ev_id, ev->pke_event_handle.b, ev->pke_event_handle.i); + bx->type_data->button_text.font_type_render = FontType_AddStringRender(FontTypeIndex{0}, std::move(str), &frs); + } + return bx; +} + +void pke_at_level_import_init() { + pke_ui_box *bx; + + lvl_mstr.data.future_service_types = g_at.data->get_service_types(); + lvl_mstr.state = state_get_service_types; + bx = pke_ui_box_new_root(); + bx->flags |= PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC; + // root->flags |= PKE_UI_BOX_FLAG_CENTER_BOTH; + bx->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE; + bx->flex_direction = 1; + bx->flex_padding = 4; + lvl_mstr.ui.root_box = bx; + pke_level_register_root_ui_box(lvl_mstr.level, bx); + + pke_ui_box *bx_bottom_bar = pke_ui_box_new_root(); + lvl_mstr.ui.root_bottom_bar = bx_bottom_bar; + bx = bx_bottom_bar; + bx->flags |= PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC; + bx->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE; + bx->flex_direction = 0; + bx->flex_padding = 4; + pke_level_register_root_ui_box(lvl_mstr.level, bx); + + pke_ui_box *bx_setlist_details = pke_ui_box_new_root(); + lvl_mstr.ui.root_setlist_details = bx_setlist_details; + bx = bx_setlist_details; + bx->flags |= PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC; + bx->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE; + pke_level_register_root_ui_box(lvl_mstr.level, bx); + + pke_ui_box *bx_setlist_items = pke_ui_box_new_root(); + lvl_mstr.ui.root_setlist_items = bx_setlist_items; + bx = bx_setlist_items; + bx->flags |= PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC; + bx->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE; + bx->flex_direction = 1; + bx->flex_padding = 4; + pke_level_register_root_ui_box(lvl_mstr.level, bx); + + lvl_mstr.ui.btn_exit = pke_at_level_import_build_ui_list_item(bx_bottom_bar, cstring_to_pk_cstr("Exit"), pke_at_level_import_exit_clicked, nullptr, PKE_UI_BOX_TYPE_BUTTON_TEXT); + lvl_mstr.ui.btn_exit->color_background = glm::vec4(1,0,0,1); + + lvl_mstr.ui.btn_back = pke_at_level_import_build_ui_list_item(bx_bottom_bar, cstring_to_pk_cstr("Back"), pke_at_level_import_back_clicked, nullptr, PKE_UI_BOX_TYPE_BUTTON_TEXT); + lvl_mstr.ui.btn_back->color_background = glm::vec4(0,0,1,1); + + bx = pke_at_level_import_build_ui_list_item(bx_bottom_bar, {}, nullptr, nullptr, PKE_UI_BOX_TYPE_STANDARD); + bx->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE; + + lvl_mstr.ui.btn_import = pke_at_level_import_build_ui_list_item(bx_bottom_bar, cstring_to_pk_cstr("Import"), pke_at_level_import_import_clicked, nullptr, PKE_UI_BOX_TYPE_BUTTON_TEXT); + lvl_mstr.ui.btn_import->color_background = glm::vec4(0,1,0,1); + lvl_mstr.ui.btn_import->flags |= PKE_UI_BOX_FLAG_VISIBILITY_DISABLED; + + pke_at_level_import_recalc_ui(); +} + +void pke_at_level_import_build_ui_service_types() { + uint32_t u; + for (u = 0; u < lvl_mstr.ui.root_box->internal.h_children; ++u) { + ECS_MarkForRemoval(lvl_mstr.ui.root_box->internal.children[u]); + } + for (u = 0; u < lvl_mstr.data.service_types.next; ++u) { + di_service_type *service_type = &lvl_mstr.data.service_types[u]; + pk_cstr title = pk_cstr_clone(&service_type->details.name, nullptr); + pke_at_level_import_build_ui_list_item(lvl_mstr.ui.root_box, std::move(title), pke_at_level_import_service_type_clicked, service_type); + } +} + +void pke_at_level_import_build_ui_upcoming_plans() { + uint32_t u; + for (u = 0; u < lvl_mstr.ui.root_box->internal.h_children; ++u) { + ECS_MarkForRemoval(lvl_mstr.ui.root_box->internal.children[u]); + } + for (u = 0; u < lvl_mstr.data.service_types.next; ++u) { + di_plan *plan = &lvl_mstr.data.plans[u]; + pk_cstr title = pk_cstr_clone(&plan->details.title, nullptr); + pke_at_level_import_build_ui_list_item(lvl_mstr.ui.root_box, std::move(title), pke_at_level_import_upcoming_plan_clicked, plan); + } +} + +void pke_at_level_import_build_ui_setlist_import_details() { + uint32_t u; + lvl_mstr.ui.btn_import->flags = static_cast<PKE_UI_BOX_FLAG>(static_cast<PKE_UI_BOX_FLAG_T>(lvl_mstr.ui.btn_import->flags) & ~static_cast<PKE_UI_BOX_FLAG_T>(PKE_UI_BOX_FLAG_VISIBILITY_DISABLED)); + + for (u = 0; u < lvl_mstr.ui.root_box->internal.h_children; ++u) { + ECS_MarkForRemoval(lvl_mstr.ui.root_box->internal.children[u]); + } + for (u = 0; u < lvl_mstr.ui.root_setlist_items->internal.h_children; ++u) { + ECS_MarkForRemoval(lvl_mstr.ui.root_setlist_items->internal.children[u]); + } + + lvl_mstr.ui.root_box->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE; + lvl_mstr.ui.root_setlist_items->flags = static_cast<PKE_UI_BOX_FLAG>(static_cast<PKE_UI_BOX_FLAG_T>(lvl_mstr.ui.root_setlist_items->flags) & ~static_cast<PKE_UI_BOX_FLAG_T>(PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE)); + lvl_mstr.ui.root_setlist_details->flags = static_cast<PKE_UI_BOX_FLAG>(static_cast<PKE_UI_BOX_FLAG_T>(lvl_mstr.ui.root_setlist_details->flags) & ~static_cast<PKE_UI_BOX_FLAG_T>(PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE)); + + for (u = 0; u < lvl_mstr.data.plan_items.next; ++u) { + pk_cstr title; + di_plan_item *plan_item = &lvl_mstr.data.plan_items[u]; + title.length = snprintf(nullptr, 0, "%li - (%s) %s", plan_item->song.details.ccli, g_keys[plan_item->details.key].name, plan_item->song.details.title.val); + title.reserved = title.length + 1; + char *str = pk_new_arr<char>(title.reserved); + snprintf(str, title.reserved, "%li - (%s) %s", plan_item->song.details.ccli, g_keys[plan_item->details.key].name, plan_item->song.details.title.val); + title.val = str; + pke_at_level_import_build_ui_list_item(lvl_mstr.ui.root_setlist_items, std::move(title), nullptr, nullptr, PKE_UI_BOX_TYPE_TEXT); + } + + pke_at_level_import_recalc_ui(); +} + +void pke_at_level_import_tick(double delta) { + (void)delta; + unsigned int u; + // state management + if (pkeSettings.rt.was_framebuffer_resized) { + pke_at_level_import_recalc_ui(); + } + if (lvl_mstr.state == state_get_service_types) { + if (lvl_mstr.data.future_service_types.wait_for(std::chrono::seconds(0)) != std::future_status::ready) { + return; + } + pke_at_data_interface_response_t<pk_arr_t<di_service_type>> resp = + lvl_mstr.data.future_service_types.get(); + if (resp.result_code == pke_at_data_interface_result_code_error) { + lvl_mstr.state = state_err_service_types; + return; + } + lvl_mstr.data.service_types = *resp.value; + pk_delete<pk_arr_t<di_service_type>>(resp.value); + lvl_mstr.data.future_service_types = {}; + lvl_mstr.state = state_display_service_types; + } + if (lvl_mstr.state == state_display_service_types) { + pke_at_level_import_build_ui_service_types(); + lvl_mstr.state = state_wait_service_types; + return; + } + if (lvl_mstr.state == state_err_service_types) { + // TODO + } + if (lvl_mstr.state == state_wait_service_types) { + // wait for user input + return; + } + if (lvl_mstr.state == state_get_upcoming_plans) { + if (lvl_mstr.data.future_upcoming_plans.wait_for(std::chrono::seconds(0)) != std::future_status::ready) { + return; + } + pke_at_data_interface_response_t<pk_arr_t<di_plan>> resp = + lvl_mstr.data.future_upcoming_plans.get(); + if (resp.result_code == pke_at_data_interface_result_code_error) { + lvl_mstr.state = state_err_upcoming_plans; + return; + } + lvl_mstr.data.plans = *resp.value; + pk_delete<pk_arr_t<di_plan>>(resp.value); + lvl_mstr.data.future_upcoming_plans = {}; + lvl_mstr.state = state_display_upcoming_plans; + } + if (lvl_mstr.state == state_display_upcoming_plans) { + pke_at_level_import_build_ui_upcoming_plans(); + lvl_mstr.state = state_wait_upcoming_plans; + return; + } + if (lvl_mstr.state == state_wait_upcoming_plans) { + // wait for user input + return; + } + if (lvl_mstr.state == state_err_upcoming_plans) { + // TODO + } + if (lvl_mstr.state == state_get_plan_items) { + pke_at_data_interface_response_t<pk_arr_t<di_plan_item>> resp = + lvl_mstr.data.future_plan_items.get(); + if (resp.result_code == pke_at_data_interface_result_code_error) { + lvl_mstr.state = state_err_plan_items; + return; + } + lvl_mstr.data.plan_items = *resp.value; + pk_delete<pk_arr_t<di_plan_item>>(resp.value); + lvl_mstr.data.future_plan_items = {}; + lvl_mstr.state = state_display_summary; + // pke_at_level_import_import_plan_items(); + // TODO + // go to saved plan picker? + // or maybe display all the info we got? + // then allow the user to import ad-hoc? + // for example, might be nice to just re-import a single song + // - this begs the question of if we should just let the user search for a song to import, in which case can I go to ccli directly instead? + } + if (lvl_mstr.state == state_err_plan_items) { + // TODO + } + if (lvl_mstr.state == state_display_summary) { + pke_at_level_import_build_ui_setlist_import_details(); + lvl_mstr.state = state_wait_summary; + return; + } + if (lvl_mstr.state == state_wait_summary) { + // wait for user input + return; + } +} + +void pke_at_level_import_teardown() { + pk_arr_reset(&lvl_mstr.data.plan_items); + pk_arr_reset(&lvl_mstr.data.plans); + pk_arr_reset(&lvl_mstr.data.service_types); + lvl_mstr.data.selected_service_type = nullptr; + lvl_mstr.data.selected_plan = nullptr; +} diff --git a/src/level-import.hpp b/src/level-import.hpp new file mode 100644 index 0000000..dd0c8a7 --- /dev/null +++ b/src/level-import.hpp @@ -0,0 +1,11 @@ +#ifndef PKE_AT_LEVEL_IMPORT_HPP +#define PKE_AT_LEVEL_IMPORT_HPP + +#include "pke/level-types.hpp" + +pke_level *pke_at_level_import_create(); +void pke_at_level_import_init(); +void pke_at_level_import_tick(double delta); +void pke_at_level_import_teardown(); + +#endif /* PKE_AT_LEVEL_IMPORT_HPP */ diff --git a/src/level-main.cpp b/src/level-main.cpp index 71999ce..a852f7d 100644 --- a/src/level-main.cpp +++ b/src/level-main.cpp @@ -1,6 +1,7 @@ #include "level-main.hpp" +#include "level-import.hpp" #include "pke-at-common.hpp" #include "pke-at-settings.hpp" @@ -9,6 +10,7 @@ struct pke_level_main_master { pke_level *level = nullptr; struct pke_level_main_master_ui { + pke_ui_box *root_btn_import = nullptr; pke_ui_box *ctrls = nullptr; pke_ui_box *btn_play_pause = nullptr; pke_ui_box *btn_stop = nullptr; @@ -99,6 +101,17 @@ void pke_at_level_main_recalc_ui() { box->pos_top_left.x = 0; box->pos_top_left.y = 0; + box = main_mstr.ui.root_btn_import; + box->flags |= PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC; + box->color_border = glm::vec4(1,1,1,1); + box->color_background = glm::vec4(.2,.2,.2,1); + box->min_size.x = 300; + box->min_size.y = 34; + box->max_size.x = 300; + box->max_size.y = 34; + box->pos_top_left.x = Extent.width - 300; + box->pos_top_left.y = 0; + pke_ui_force_recalc(); } @@ -115,15 +128,15 @@ void pke_at_level_main_btn_play_pause_cb(void *ev_data, void *cb_data, void *em_ (void)em_data; if (!PK_HAS_FLAG(g_at.rt.flags, PKE_AT_RUNTIME_FLAG_PLAYING)) { g_at.rt.flags |= PKE_AT_RUNTIME_FLAG_PLAYING; - FontType_UpdateStringRenderText(main_mstr.ui.btn_play_pause->type_data->button_text.font_render_handle, cstring_to_pk_cstr("Pause")); + FontType_UpdateStringRenderText(main_mstr.ui.btn_play_pause->type_data->button_text.font_type_render, cstring_to_pk_cstr("Pause")); return; } if (!PK_HAS_FLAG(g_at.rt.flags, PKE_AT_RUNTIME_FLAG_PAUSED)) { g_at.rt.flags |= PKE_AT_RUNTIME_FLAG_PAUSED; - FontType_UpdateStringRenderText(main_mstr.ui.btn_play_pause->type_data->button_text.font_render_handle, cstring_to_pk_cstr("Resume")); + FontType_UpdateStringRenderText(main_mstr.ui.btn_play_pause->type_data->button_text.font_type_render, cstring_to_pk_cstr("Resume")); } else { g_at.rt.flags &= ~PKE_AT_RUNTIME_FLAG_PAUSED; - FontType_UpdateStringRenderText(main_mstr.ui.btn_play_pause->type_data->button_text.font_render_handle, cstring_to_pk_cstr("Pause")); + FontType_UpdateStringRenderText(main_mstr.ui.btn_play_pause->type_data->button_text.font_type_render, cstring_to_pk_cstr("Pause")); } } @@ -133,7 +146,7 @@ void pke_at_level_main_btn_stop_cb(void *ev_data, void *cb_data, void *em_data) (void)em_data; g_at.rt.flags &= ~(PKE_AT_RUNTIME_FLAG_PLAYING | PKE_AT_RUNTIME_FLAG_PAUSED); pke_at_bpm_reset(g_at.bpm.target); - FontType_UpdateStringRenderText(main_mstr.ui.btn_play_pause->type_data->button_text.font_render_handle, cstring_to_pk_cstr("Play")); + FontType_UpdateStringRenderText(main_mstr.ui.btn_play_pause->type_data->button_text.font_type_render, cstring_to_pk_cstr("Play")); } void pke_at_level_main_btn_next_cb(void *ev_data, void *cb_data, void *em_data) { @@ -143,63 +156,82 @@ void pke_at_level_main_btn_next_cb(void *ev_data, void *cb_data, void *em_data) // TODO } +void pke_at_level_main_btn_import_cb(void *ev_data, void *cb_data, void *em_data) { + (void)ev_data; + (void)cb_data; + (void)em_data; + pkeSettings.rt.nextLevel = pke_at_level_import_create(); +} + void pke_at_level_main_init() { FontRenderSettings frs{}; pke_ui_box *ctrls = pke_ui_box_new_root(); + pke_ui_box *root_btn_import = pke_ui_box_new_root(PKE_UI_BOX_TYPE_BUTTON_TEXT); pke_level_register_root_ui_box(main_mstr.level, ctrls); + pke_level_register_root_ui_box(main_mstr.level, root_btn_import); main_mstr.ui.ctrls = ctrls; + main_mstr.ui.root_btn_import = root_btn_import; pke_ui_box *btn_prev_track = pke_ui_box_new_child(ctrls, PKE_UI_BOX_TYPE_BUTTON_TEXT); main_mstr.ui.btn_prev_track = btn_prev_track; - frs.char_scale = 12; + frs.char_scale = 16; frs.color_background = glm::vec4(0,0,0,1); frs.color_foreground = glm::vec4(1,0,0,1); frs.surface_area_type_flags = FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_BOTH; - FontRenderHandle fr_prev = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr(" < "), &frs); - btn_prev_track->type_data->button_text.font_render_handle = fr_prev; + FontTypeRender fr_prev = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr(" < "), &frs); + btn_prev_track->type_data->button_text.font_type_render = fr_prev; pke_component_event *prev_ev = ECS_CreateEv(btn_prev_track, pk_uuid_max); pk_ev_register_cb(prev_ev->ev_mgr_id, prev_ev->ev_id, pke_at_level_main_btn_prev_cb, nullptr); btn_prev_track->type_data->button_text.pke_event_handle = prev_ev->pke_event_handle; pke_ui_box *btn_play_pause = pke_ui_box_new_child(ctrls, PKE_UI_BOX_TYPE_BUTTON_TEXT); main_mstr.ui.btn_play_pause = btn_play_pause; - frs.char_scale = 12; + frs.char_scale = 16; frs.color_background = glm::vec4(0,0,0,1); frs.color_foreground = glm::vec4(0,1,0,1); frs.surface_area_type_flags = FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_BOTH; - FontRenderHandle fr_play = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr(" Play "), &frs); - btn_play_pause->type_data->button_text.font_render_handle = fr_play; + FontTypeRender fr_play = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr(" Play "), &frs); + btn_play_pause->type_data->button_text.font_type_render = fr_play; pke_component_event *play_pause_ev = ECS_CreateEv(btn_play_pause, pk_uuid_max); pk_ev_register_cb(play_pause_ev->ev_mgr_id, play_pause_ev->ev_id, pke_at_level_main_btn_play_pause_cb, nullptr); btn_play_pause->type_data->button_text.pke_event_handle = play_pause_ev->pke_event_handle; pke_ui_box *btn_stop = pke_ui_box_new_child(ctrls, PKE_UI_BOX_TYPE_BUTTON_TEXT); main_mstr.ui.btn_stop = btn_stop; - frs.char_scale = 12; + frs.char_scale = 16; frs.color_background = glm::vec4(0,0,0,1); frs.color_foreground = glm::vec4(0.5,0.5,0,1); frs.surface_area_type_flags = FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_BOTH; - FontRenderHandle fr_stop = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr(" Stop "), &frs); - btn_stop->type_data->button_text.font_render_handle = fr_stop; + FontTypeRender fr_stop = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr(" Stop "), &frs); + btn_stop->type_data->button_text.font_type_render = fr_stop; pke_component_event *stop_ev = ECS_CreateEv(btn_stop, pk_uuid_max); pk_ev_register_cb(stop_ev->ev_mgr_id, stop_ev->ev_id, pke_at_level_main_btn_stop_cb, nullptr); btn_stop->type_data->button_text.pke_event_handle = stop_ev->pke_event_handle; pke_ui_box *btn_next_track = pke_ui_box_new_child(ctrls, PKE_UI_BOX_TYPE_BUTTON_TEXT); main_mstr.ui.btn_next_track = btn_next_track; - frs.char_scale = 12; + frs.char_scale = 16; frs.color_background = glm::vec4(0,0,0,1); frs.color_foreground = glm::vec4(0,0,1,1); frs.surface_area_type_flags = FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_BOTH; - FontRenderHandle fr_next = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr(" > "), &frs); - btn_next_track->type_data->button_text.font_render_handle = fr_next; + FontTypeRender fr_next = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr(" > "), &frs); + btn_next_track->type_data->button_text.font_type_render = fr_next; pke_component_event *next_ev = ECS_CreateEv(btn_next_track, pk_uuid_max); pk_ev_register_cb(next_ev->ev_mgr_id, next_ev->ev_id, pke_at_level_main_btn_next_cb, nullptr); btn_next_track->type_data->button_text.pke_event_handle = next_ev->pke_event_handle; + frs.char_scale = 16; + frs.color_background = glm::vec4(0,0,0,1); + frs.color_foreground = glm::vec4(1,1,1,1); + frs.surface_area_type_flags = FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_CENTER_BOTH; + pke_component_event *import_ev = ECS_CreateEv(main_mstr.ui.root_btn_import, pk_uuid_max); + main_mstr.ui.root_btn_import->type_data->button_text.pke_event_handle = import_ev->pke_event_handle; + pk_ev_register_cb(import_ev->ev_mgr_id, import_ev->ev_id, pke_at_level_main_btn_import_cb, nullptr); + main_mstr.ui.root_btn_import->type_data->button_text.font_type_render = FontType_AddStringRender(FontTypeIndex{0}, cstring_to_pk_cstr("IMPORT"), &frs); + pke_at_bpm_reset(120); - g_at.mtrnm.beep = pke_at_audio_get_or_generate_sawtooth(440.f, 0.30); - g_at.mtrnm.beep_accent = pke_at_audio_get_or_generate_sawtooth(440.f * (3/2.f), 0.30); + g_at.mtrnm.beep = g_keys[PKE_AT_KEY_INDEX_B].mtrnm_beat_asset_handle; + g_at.mtrnm.beep_accent = g_keys[PKE_AT_KEY_INDEX_B].mtrnm_down_beat_asset_handle; pke_audio_set_volume(pke_audio_source_sfx, 0.25); g_at.rt.flags = PKE_AT_RUNTIME_FLAG_NONE; diff --git a/src/pke-at-data-interface.hpp b/src/pke-at-data-interface.hpp index ec10747..b57fe58 100644 --- a/src/pke-at-data-interface.hpp +++ b/src/pke-at-data-interface.hpp @@ -30,8 +30,8 @@ struct pke_at_data_interface { virtual void init() const = 0; virtual void teardown() const = 0; virtual FPADIRT(pk_arr_t<di_service_type>) get_service_types() const = 0; - virtual FPADIRT(pk_arr_t<di_plan>) get_plans_upcoming_from_service_type() const = 0; - virtual FPADIRT(pk_arr_t<di_plan_item>) get_plan_items() const = 0; + virtual FPADIRT(pk_arr_t<di_plan>) get_plans_upcoming_from_service_type(di_service_type *service_type) const = 0; + virtual FPADIRT(pk_arr_t<di_plan_item>) get_plan_items(di_plan *plan) const = 0; // virtual FPADIRT(pk_arr_t<pke_at_plan_details>) get_song_arrangements() const = 0; }; diff --git a/src/pke-at-data-planning-center.hpp b/src/pke-at-data-planning-center.hpp new file mode 100644 index 0000000..c3fd680 --- /dev/null +++ b/src/pke-at-data-planning-center.hpp @@ -0,0 +1,6 @@ +#ifndef PKE_AT_PKE_AT_DATA_PLANNING_CENTER_HPP +#define PKE_AT_PKE_AT_DATA_PLANNING_CENTER_HPP + + + +#endif /* PKE_AT_PKE_AT_DATA_PLANNING_CENTER_HPP */ diff --git a/src/pke-at-data-stub.cpp b/src/pke-at-data-stub.cpp index c36583f..d539f11 100644 --- a/src/pke-at-data-stub.cpp +++ b/src/pke-at-data-stub.cpp @@ -15,8 +15,9 @@ void pke_at_data_stub::teardown() const { FPADIRT(pk_arr_t<di_service_type>) pke_at_data_stub::get_service_types() const { - PPADIRT(pk_arr_t<di_service_type>) ret{}; - std::thread([&ret]() { + static PPADIRT(pk_arr_t<di_service_type>) ret{}; + ret = {}; + std::thread([]() { pke_at_data_interface_response_t<pk_arr_t<di_service_type>> val{}; val.result_code = pke_at_data_interface_result_code_success; val.value = pk_new<pk_arr_t<di_service_type>>(); @@ -27,9 +28,11 @@ pke_at_data_stub::get_service_types() const { }; FPADIRT(pk_arr_t<di_plan>) -pke_at_data_stub::get_plans_upcoming_from_service_type() const { - PPADIRT(pk_arr_t<di_plan>) ret{}; - std::thread([&ret]() { +pke_at_data_stub::get_plans_upcoming_from_service_type(di_service_type *service_type) const { + (void)service_type; + static PPADIRT(pk_arr_t<di_plan>) ret{}; + ret = {}; + std::thread([]() { pke_at_data_interface_response_t<pk_arr_t<di_plan>> val{}; val.result_code = pke_at_data_interface_result_code_success; val.value = pk_new<pk_arr_t<di_plan>>(); @@ -40,9 +43,11 @@ pke_at_data_stub::get_plans_upcoming_from_service_type() const { } FPADIRT(pk_arr_t<di_plan_item>) -pke_at_data_stub::get_plan_items() const { - PPADIRT(pk_arr_t<di_plan_item>) ret{}; - std::thread([&ret]() { +pke_at_data_stub::get_plan_items(di_plan *plan) const { + (void)plan; + static PPADIRT(pk_arr_t<di_plan_item>) ret{}; + ret = {}; + std::thread([]() { pke_at_data_interface_response_t<pk_arr_t<di_plan_item>> val{}; val.result_code = pke_at_data_interface_result_code_success; val.value = pk_new<pk_arr_t<di_plan_item>>(); diff --git a/src/pke-at-data-stub.hpp b/src/pke-at-data-stub.hpp index 4f8d929..a875ee3 100644 --- a/src/pke-at-data-stub.hpp +++ b/src/pke-at-data-stub.hpp @@ -7,8 +7,8 @@ class pke_at_data_stub : public pke_at_data_interface { void init() const override; void teardown() const override; FPADIRT(pk_arr_t<di_service_type>) get_service_types() const override; - FPADIRT(pk_arr_t<di_plan>) get_plans_upcoming_from_service_type() const override; - FPADIRT(pk_arr_t<di_plan_item>) get_plan_items() const override; + FPADIRT(pk_arr_t<di_plan>) get_plans_upcoming_from_service_type(di_service_type *service_type) const override; + FPADIRT(pk_arr_t<di_plan_item>) get_plan_items(di_plan *plan) const override; // FPADIRT(pk_arr_t<pke_at_plan_details>) get_song_arrangements() const override; }; diff --git a/src/pke-at-setlist-types.cpp b/src/pke-at-setlist-types.cpp new file mode 100644 index 0000000..9aeea2b --- /dev/null +++ b/src/pke-at-setlist-types.cpp @@ -0,0 +1,23 @@ + +#include "pke-at-setlist-types.hpp" + +pke_at_key g_keys[PKE_AT_KEY_INDEX_COUNT] = { + { "NIL", 0, 0 }, + { "C", 523.2511, 523.2511 * (3/2.f) }, + { "C♯", 554.3653, 554.3653 * (3/2.f) }, + { "D♭", 554.3653, 554.3653 * (3/2.f) }, + { "D", 587.3295, 587.3295 * (3/2.f) }, + { "D♯", 622.2540, 622.2540 * (3/2.f) }, + { "E♭", 622.2540, 622.2540 * (3/2.f) }, + { "E", 659.2551, 659.2551 * (3/2.f) }, + { "F", 698.4565, 698.4565 * (3/2.f) }, + { "F♯", 739.9888, 739.9888 * (3/2.f) }, + { "G♭", 739.9888, 739.9888 * (3/2.f) }, + { "G", 783.9909, 783.9909 * (3/2.f) }, + { "G♯", 830.6094, 830.6094 * (3/2.f) }, + { "A♭", 830.6094, 830.6094 * (3/2.f) }, + { "A", 880.0000, 880.0000 * (3/2.f) }, + { "A♯", 932.3275, 932.3275 * (3/2.f) }, + { "B♭", 932.3275, 932.3275 * (3/2.f) }, + { "B", 987.7666, 987.7666 * (3/2.f) }, +}; diff --git a/src/pke-at-setlist-types.hpp b/src/pke-at-setlist-types.hpp index 90c86d0..242df69 100644 --- a/src/pke-at-setlist-types.hpp +++ b/src/pke-at-setlist-types.hpp @@ -89,4 +89,13 @@ struct pke_at_setlist_song { struct pke_at_setlist_song_details details{}; }; +struct pke_at_key { + const char *name; + float mtrnm_hz_beat; + float mtrnm_hz_down_beat; + AssetHandle mtrnm_beat_asset_handle = AssetHandle_MAX; + AssetHandle mtrnm_down_beat_asset_handle = AssetHandle_MAX; +}; +extern struct pke_at_key g_keys[PKE_AT_KEY_INDEX_COUNT]; + #endif /* PKE_AT_PKE_AT_SETLIST_TYPES_HPP */ diff --git a/src/pke-at-settings.hpp b/src/pke-at-settings.hpp index dd50532..81074d4 100644 --- a/src/pke-at-settings.hpp +++ b/src/pke-at-settings.hpp @@ -19,6 +19,7 @@ struct pke_at_global_settings { pk_membucket *bkt_transient; } mem; struct pke_at_storage_interface *storage; + struct pke_at_data_interface *data; struct pke_at_global_settings_bpm { float last; float target; diff --git a/src/pke-at.cpp b/src/pke-at.cpp index 0831c08..f53d2eb 100644 --- a/src/pke-at.cpp +++ b/src/pke-at.cpp @@ -1,5 +1,7 @@ #include "level-init.hpp" +#include "pke-at-common.hpp" +#include "pke-at-data-stub.hpp" #include "pke-at-setlist-types.hpp" #include "pke-at-settings.hpp" #include "pke-at-storage-sql.hpp" @@ -17,16 +19,26 @@ void pke_at_tick(double delta) { } void pke_at_init() { - uint64_t i; + uint64_t u; pkeSettings.rt.nextLevel = pke_at_level_init_create(); - for (i = 0; i < PKE_AT_SECTION_TYPE_INDEX_COUNT; ++i) { - if (g_section_types[i].title_key[0] == '\0') continue; - g_section_types[i].title_handle = AM_GetHandle(g_section_types[i].title_key); + for (u = 0; u < PKE_AT_SECTION_TYPE_INDEX_COUNT; ++u) { + if (g_section_types[u].title_key[0] == '\0') continue; + g_section_types[u].title_handle = AM_GetHandle(g_section_types[u].title_key); + } + + for (u = 1; u < PKE_AT_KEY_INDEX_COUNT; ++u) { + g_keys[u].mtrnm_beat_asset_handle = + pke_at_audio_get_or_generate_sawtooth(g_keys[u].mtrnm_hz_beat, 0.3); + g_keys[u].mtrnm_down_beat_asset_handle = + pke_at_audio_get_or_generate_sawtooth(g_keys[u].mtrnm_hz_down_beat, 0.3); } g_at.storage = pk_new<pke_at_storage_sql>(); g_at.storage->init(); + + g_at.data = pk_new<pke_at_data_stub>(); + g_at.data->init(); } void pke_at_teardown() { |
