Login
1 branch 0 tags
Ben (Desktop/Arch) Switched to RGB565_SWAPPED for more efficient rendering bc79297 1 month ago 73 Commits
moon / src / main.c
#include "audio_player.h"
#include "lvgl.h"
#include "moon.h"
#include "playlist.h"
#include "screens/audiobooks_screen.h"
#include "screens/files_screen.h"
#include "screens/home_screen.h"
#include "screens/music_screen.h"
#include "screens/now_playing_screen.h"
#include "screens/queue_dialog_screen.h"
#include "screens/settings_screen.h"
#include "screens/usb_screen.h"
#include "storage.h"

#ifdef ESP_PLATFORM
#include "usb_msc.h"
#endif
#include "topbar.h"
#include "ui.h"

#include "fonts/fonts.h"

uint8_t button_state;

app_state_t app_state = {0};
ui_state_t ui_state = {0};

ui_state_t setup_screen(screen_type_t type, lv_obj_t* parent) {
	set_display_brightness(255);
	switch (type) {
		case SCREEN_HOME:
			return setup_home_screen(parent);
		case SCREEN_FILES:
			return setup_files_screen(parent, "/", "");
		case SCREEN_NOW_PLAYING:
			return setup_now_playing_screen(parent);
		case SCREEN_QUEUE_DIALOG:
			return setup_queue_dialog_screen(parent);
		case SCREEN_AUDIOBOOKS:
			return setup_audiobooks_screen(parent, AUDIOBOOKS_ROOT, "");
		case SCREEN_MUSIC:
			return setup_music_screen(parent, MUSIC_ROOT, "");
		case SCREEN_SETTINGS:
			return setup_settings_screen(parent);
		case SCREEN_USB:
			return setup_usb_screen(parent);
		case SCREEN_CONFIRM:
			return setup_confirm_screen(parent);
		default:
			return (ui_state_t){0};
	}
}

void free_screen(void) {
	// Remove all objects from input group before freeing state
	lv_group_remove_all_objs(lv_group_get_default());

	switch (ui_state.type) {
		case SCREEN_HOME:
			free_home_screen(ui_state.home);
			break;
		case SCREEN_FILES:
			free_files_screen(ui_state.files);
			break;
		case SCREEN_NOW_PLAYING:
			free_now_playing_screen(ui_state.now_playing);
			break;
		case SCREEN_QUEUE_DIALOG:
			free_queue_dialog_screen(ui_state.queue_dialog);
			break;
		case SCREEN_AUDIOBOOKS:
			free_audiobooks_screen(ui_state.audiobooks);
			break;
		case SCREEN_MUSIC:
			free_music_screen(ui_state.music);
			break;
		case SCREEN_SETTINGS:
			free_settings_screen(ui_state.settings);
			break;
		case SCREEN_USB:
			free_usb_screen(ui_state.usb);
			break;
		case SCREEN_CONFIRM:
			free_confirm_screen(ui_state.confirm);
			break;
		default:
			break;
	}
	ui_state = (ui_state_t){0};
}

void update_screen(void) {
	switch (ui_state.type) {
		case SCREEN_HOME:
			update_home_screen(ui_state.home);
			break;
		case SCREEN_FILES:
			update_files_screen(ui_state.files);
			break;
		case SCREEN_NOW_PLAYING:
			update_now_playing_screen(ui_state.now_playing);
			break;
		case SCREEN_QUEUE_DIALOG:
			update_queue_dialog_screen(ui_state.queue_dialog);
			break;
		case SCREEN_AUDIOBOOKS:
			update_audiobooks_screen(ui_state.audiobooks);
			break;
		case SCREEN_MUSIC:
			update_music_screen(ui_state.music);
			break;
		case SCREEN_SETTINGS:
			update_settings_screen(ui_state.settings);
			break;
		case SCREEN_USB:
			update_usb_screen(ui_state.usb);
			break;
		default:
			break;
	}
}

void setup(void) {
	// Initialize storage subsystem
	storage_init();

	// Load playlist from SD card
	playlist_load();

	// Initialize audio player
	audio_player_init();

	// Set up dark theme with custom accent color
	lv_display_t* disp = lv_display_get_default();
	lv_theme_t* theme =
	    lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_PINK),
	                          lv_palette_main(LV_PALETTE_LIGHT_BLUE),
	                          true,  // Dark mode
	                          &roboto_condensed);
	lv_display_set_theme(disp, theme);

	// Solid dark background on bottom layer to prevent seeing
	// "nothing" behind sliding screens during transitions
	lv_obj_t* bg = lv_obj_create(lv_layer_bottom());
	lv_obj_set_size(bg, SCREEN_WIDTH, SCREEN_HEIGHT);
	lv_obj_set_style_bg_color(bg, lv_color_hex(0x1A1A1A), 0);
	lv_obj_set_style_bg_opa(bg, LV_OPA_COVER, 0);
	lv_obj_set_style_border_width(bg, 0, 0);
	lv_obj_set_style_radius(bg, 0, 0);

	topbar_create();
	ui_state = setup_screen(SCREEN_HOME, lv_screen_active());
}

void loop(void) {
#ifdef ESP_PLATFORM
	// Auto-switch to USB screen when host connects
	if (ui_state.type != SCREEN_USB && usb_msc_host_connected()) {
		navigate_none(SCREEN_USB);
		return;
	}
#endif
	audio_player_update();
	playlist_tick();
	topbar_update();
	update_screen();
}