Login
1 branch 0 tags
Ben (Desktop/Arch) Audio stuff! a833fb5 1 month ago 18 Commits
moon / firmware / src / screens / player_screen.c
#include "player_screen.h"
#include "../audio_player.h"
#include <stdlib.h>
#include <string.h>

static void cancel_event_cb(lv_event_t *e) {
    (void)e;
    audio_player_stop();
    navigate_to(SCREEN_FILES);
}

static void play_btn_cb(lv_event_t *e) {
    lv_event_code_t code = lv_event_get_code(e);
    if (code == LV_EVENT_CLICKED) {
        audio_state_t state = audio_player_get_state();
        if (state == AUDIO_STATE_PLAYING) {
            audio_player_pause();
        } else if (state == AUDIO_STATE_PAUSED) {
            audio_player_resume();
        }
    }
}

static void stop_btn_cb(lv_event_t *e) {
    lv_event_code_t code = lv_event_get_code(e);
    if (code == LV_EVENT_CLICKED) {
        audio_player_stop();
        navigate_to(SCREEN_FILES);
    }
}

static void back_btn_cb(lv_event_t *e) {
    lv_event_code_t code = lv_event_get_code(e);
    if (code == LV_EVENT_CLICKED) {
        audio_player_stop();
        navigate_to(SCREEN_FILES);
    }
}

ui_state_t setup_player_screen(void) {
    player_screen_state_t *state = calloc(1, sizeof(player_screen_state_t));

    // Main container
    state->container = lv_obj_create(lv_screen_active());
    lv_obj_set_size(state->container, LV_PCT(100), LV_PCT(100));
    lv_obj_set_flex_flow(state->container, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(state->container, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_pad_all(state->container, 8, 0);
    lv_obj_set_style_pad_gap(state->container, 8, 0);

    // Title - "Now Playing"
    lv_obj_t *header = lv_label_create(state->container);
    lv_label_set_text(header, "Now Playing");
    lv_obj_set_style_text_color(header, lv_color_hex(0xE91E63), 0);

    // Filename label
    state->title_label = lv_label_create(state->container);
    const char *filename = audio_player_get_filename();
    lv_label_set_text(state->title_label, filename ? filename : "Unknown");
    lv_label_set_long_mode(state->title_label, LV_LABEL_LONG_SCROLL_CIRCULAR);
    lv_obj_set_width(state->title_label, LV_PCT(90));

    // Status label
    state->status_label = lv_label_create(state->container);
    lv_label_set_text(state->status_label, LV_SYMBOL_PLAY " Playing");
    lv_obj_set_style_text_color(state->status_label, lv_color_hex(0x4CAF50), 0);

    // Button container
    lv_obj_t *btn_cont = lv_obj_create(state->container);
    lv_obj_set_size(btn_cont, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_flex_flow(btn_cont, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(btn_cont, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_pad_all(btn_cont, 4, 0);
    lv_obj_set_style_border_width(btn_cont, 0, 0);
    lv_obj_set_style_bg_opa(btn_cont, LV_OPA_TRANSP, 0);

    // Play/Pause button
    state->play_btn = lv_button_create(btn_cont);
    lv_obj_set_size(state->play_btn, 40, 40);
    lv_obj_t *play_label = lv_label_create(state->play_btn);
    lv_label_set_text(play_label, LV_SYMBOL_PAUSE);
    lv_obj_center(play_label);
    lv_obj_add_event_cb(state->play_btn, play_btn_cb, LV_EVENT_CLICKED, state);
    lv_obj_add_event_cb(state->play_btn, cancel_event_cb, LV_EVENT_CANCEL, NULL);
    lv_group_add_obj(lv_group_get_default(), state->play_btn);

    // Stop button
    state->stop_btn = lv_button_create(btn_cont);
    lv_obj_set_size(state->stop_btn, 40, 40);
    lv_obj_t *stop_label = lv_label_create(state->stop_btn);
    lv_label_set_text(stop_label, LV_SYMBOL_STOP);
    lv_obj_center(stop_label);
    lv_obj_add_event_cb(state->stop_btn, stop_btn_cb, LV_EVENT_CLICKED, NULL);
    lv_obj_add_event_cb(state->stop_btn, cancel_event_cb, LV_EVENT_CANCEL, NULL);
    lv_group_add_obj(lv_group_get_default(), state->stop_btn);

    // Back button
    state->back_btn = lv_button_create(btn_cont);
    lv_obj_set_size(state->back_btn, 40, 40);
    lv_obj_t *back_label = lv_label_create(state->back_btn);
    lv_label_set_text(back_label, LV_SYMBOL_LEFT);
    lv_obj_center(back_label);
    lv_obj_add_event_cb(state->back_btn, back_btn_cb, LV_EVENT_CLICKED, NULL);
    lv_obj_add_event_cb(state->back_btn, cancel_event_cb, LV_EVENT_CANCEL, NULL);
    lv_group_add_obj(lv_group_get_default(), state->back_btn);

    // Focus play button by default
    lv_group_focus_obj(state->play_btn);

    return (ui_state_t){.type = SCREEN_PLAYER, .player = state};
}

void free_player_screen(player_screen_state_t *state) {
    if (!state) return;

    lv_group_remove_obj(state->play_btn);
    lv_group_remove_obj(state->stop_btn);
    lv_group_remove_obj(state->back_btn);

    lv_obj_delete(state->container);
    free(state);
}

void update_player_screen(player_screen_state_t *state) {
    if (!state) return;

    audio_state_t audio_state = audio_player_get_state();

    // Update play/pause button icon
    lv_obj_t *play_label = lv_obj_get_child(state->play_btn, 0);
    if (audio_state == AUDIO_STATE_PLAYING) {
        lv_label_set_text(play_label, LV_SYMBOL_PAUSE);
        lv_label_set_text(state->status_label, LV_SYMBOL_PLAY " Playing");
        lv_obj_set_style_text_color(state->status_label, lv_color_hex(0x4CAF50), 0);
    } else if (audio_state == AUDIO_STATE_PAUSED) {
        lv_label_set_text(play_label, LV_SYMBOL_PLAY);
        lv_label_set_text(state->status_label, LV_SYMBOL_PAUSE " Paused");
        lv_obj_set_style_text_color(state->status_label, lv_color_hex(0xFFA000), 0);
    } else if (audio_state == AUDIO_STATE_ERROR) {
        lv_label_set_text(play_label, LV_SYMBOL_PLAY);
        lv_label_set_text(state->status_label, LV_SYMBOL_WARNING " Error: file too large");
        lv_obj_set_style_text_color(state->status_label, lv_color_hex(0xF44336), 0);
    } else {
        lv_label_set_text(play_label, LV_SYMBOL_PLAY);
        lv_label_set_text(state->status_label, LV_SYMBOL_STOP " Stopped");
        lv_obj_set_style_text_color(state->status_label, lv_color_hex(0x757575), 0);
    }
}