Files
tactility_apps/Apps/DiscoveryMountain/main/Source/main.c
T
Adolfo be9229b80d refactor(DiscoveryMountain): split monolithic main.c into modular files
- Extracted app_context (global AppCtx G definition)
- storage: path helpers, LRU, sort, fmt_time, per-episode resume map, state persistence
- network: resolve_host, normalize URL, http_get_raw with growing PSRAM buffer, fetch_data
- download: dl_ep_raw with progress tracking, cancel, overlay UI (show/hide/update)
- player: audio device, stream, play_task with resume seek, start/select/next/prev with position save/restore
- ui: build_ui, timers, season picker, button callbacks, periodic save
- main: minimal glue, fetch_task, onShow/onHide, app registration
- Preserves all previous fixes: download progress overlay, per-episode resume, robust download handling
- Build verified: 111 undef, all exported
2026-07-22 17:11:59 -04:00

122 lines
3.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <tt_app.h>
#include <tt_lvgl.h>
#include "app_context.h"
#include "storage.h"
#include "network.h"
#include "download.h"
#include "player.h"
#include "ui.h"
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
static void fetch_task_fn(void* arg){
(void)arg;
G.fetching=true;
ESP_LOGI(TAG,"fetch task start");
fetch_data();
ESP_LOGI(TAG,"fetch done seasons=%d eps=%d",G.season_cnt,G.ep_cnt);
if(strlen(G.last_slug)>0){
for(int i=0;i<G.ep_cnt;i++) if(strcmp(G.eps[i].slug,G.last_slug)==0){ G.cur_ep_idx=i; G.cur_season=G.eps[i].season; break; }
}
if(G.cur_ep_idx<0){
int s1=-1;
for(int i=0;i<G.ep_cnt;i++) if(G.eps[i].season==G.cur_season){ s1=i; break; }
if(s1==-1) s1=0;
G.cur_ep_idx=s1;
}
tt_lvgl_lock(portMAX_DELAY);
if(G.ep_cnt>0 && G.cur_ep_idx>=0){
EpInfo* ep=&G.eps[G.cur_ep_idx];
int saved = get_saved_pos_for_slug(ep->slug);
if(saved==0) saved = G.pos_sec;
if(G.lbl_title) lv_label_set_text(G.lbl_title,ep->title);
if(G.lbl_meta){
char b[64];
if(saved>5){
char tbuf[16];
fmt_time(tbuf,saved);
snprintf(b,sizeof(b),"S%02d E%02d %s • %s",ep->season,ep->ep_num,ep->seen?"*":"",tbuf);
} else {
snprintf(b,sizeof(b),"S%02d E%02d %s",ep->season,ep->ep_num,ep->seen?"*":"");
}
lv_label_set_text(G.lbl_meta,b);
}
if(G.lbl_status){
if(saved>5) lv_label_set_text(G.lbl_status,"Resume – tap Play");
else lv_label_set_text(G.lbl_status,ep->seen?"On SD – tap Play":"Tap Play to DL");
}
if(G.bar) lv_bar_set_value(G.bar,0,LV_ANIM_OFF);
if(G.lbl_time){
if(saved>5){
char a[16];
fmt_time(a,saved);
char buf[40];
snprintf(buf,sizeof(buf),"%s / --:--",a);
lv_label_set_text(G.lbl_time,buf);
} else {
lv_label_set_text(G.lbl_time,"0:00 / --:--");
}
}
if(saved>0) G.pos_sec=saved;
} else {
if(G.lbl_status) lv_label_set_text(G.lbl_status,"No data");
}
tt_lvgl_unlock();
G.fetching=false;
G.fetch_handle=NULL;
save_state();
vTaskDelete(NULL);
}
static void onShow(AppHandle app, void* data, lv_obj_t* parent){
(void)app; (void)data; (void)parent;
memset(&G,0,sizeof(G));
G.pos_sec=0;
G.total_sec=0;
G.cur_season=1;
G.cur_ep_idx=-1;
G.volume=80;
G.last_pct=-1;
G.dl_last_pct=-1;
G.dl_expected=-1;
ensure_dir();
load_state();
build_ui();
xTaskCreate(fetch_task_fn,"dm_fetch",16384,NULL,5,&G.fetch_handle);
}
static void onHide(AppHandle app, void* data){
(void)app; (void)data;
save_current_ep_pos();
tt_lvgl_lock(portMAX_DELAY);
if(G.fetch_handle){
vTaskDelete(G.fetch_handle);
G.fetch_handle=NULL;
G.fetching=false;
}
if(G.dl_handle){
G.dl_cancel_req=true;
vTaskDelay(pdMS_TO_TICKS(100));
if(G.dl_handle){
vTaskDelete(G.dl_handle);
G.dl_handle=NULL;
G.downloading=false;
if(G.dl_overlay) hide_dl_overlay();
}
}
wait_play_exit();
close_overlay();
if(G.dl_overlay) hide_dl_overlay();
tt_lvgl_unlock();
save_state();
}
int main(int argc, char* argv[]){
(void)argc; (void)argv;
tt_app_register((AppRegistration){ .onShow=onShow, .onHide=onHide });
return 0;
}