latest change on laptop Bible and SDDownload

This commit is contained in:
Adolfo
2026-09-11 10:51:52 -04:00
parent 74fe10f130
commit e0c5cbc1a0
2 changed files with 338 additions and 48 deletions
+72 -29
View File
@@ -21,6 +21,7 @@
#define DEFAULT_PATH "/sdcard/download/test2.mp3"
typedef struct {
lv_obj_t *root_obj;
lv_obj_t *bar;
lv_obj_t *lbl_url;
lv_obj_t *lbl_path;
@@ -37,6 +38,7 @@ typedef struct {
TaskHandle_t dl_handle;
volatile bool downloading;
volatile bool cancel_req;
volatile bool task_exited;
volatile int total;
volatile int expected;
int last_pct;
@@ -82,13 +84,18 @@ static void ensure_parent_dir(const char *filepath) {
}
}
#define DL_DOWNLOADED 0
#define DL_EXISTED 1
#define DL_FAILED -1
static void update_ui_status(const char *txt) {
tt_lvgl_lock(portMAX_DELAY);
if (G.lbl_status) lv_label_set_text(G.lbl_status, txt);
tt_lvgl_unlock();
}
static void set_result_and_close(bool success) {
static void set_result_and_close(int dl_res) {
bool success = (dl_res != DL_FAILED);
G.result_success = success;
size_t free_internal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
BundleHandle result_bundle = NULL;
@@ -97,6 +104,13 @@ static void set_result_and_close(bool success) {
}
if (result_bundle) {
tt_bundle_put_bool(result_bundle, "success", success);
if (dl_res == DL_DOWNLOADED) {
tt_bundle_put_string(result_bundle, "status", "downloaded");
} else if (dl_res == DL_EXISTED) {
tt_bundle_put_string(result_bundle, "status", "existed");
} else {
tt_bundle_put_string(result_bundle, "status", "failure");
}
// Keep bundle minimal to avoid low heap crash (previous put_string path 512B caused OOM)
tt_app_set_result(G.app_handle, success ? APP_RESULT_OK : APP_RESULT_ERROR, result_bundle);
} else {
@@ -106,16 +120,9 @@ static void set_result_and_close(bool success) {
}
tt_app_set_result(G.app_handle, success ? APP_RESULT_OK : APP_RESULT_ERROR, NULL);
}
// Change Cancel button to Close once done (manual close, auto-close unreliable)
tt_lvgl_lock(portMAX_DELAY);
if (G.btn_cancel) {
lv_obj_t* lbl = lv_obj_get_child(G.btn_cancel, 0);
if (lbl) lv_label_set_text(lbl, "Close");
}
tt_lvgl_unlock();
}
static bool download_one_file(const char *url, const char *path) {
static int download_one_file(const char *url, const char *path) {
ESP_LOGI(TAG, "DL one file url=%s path=%s override=%d", url, path, G.override_existing);
struct stat st;
@@ -124,7 +131,7 @@ static bool download_one_file(const char *url, const char *path) {
ESP_LOGW(TAG, "File exists and override=false: %s (returning true as cached)", path);
G.total = st.st_size;
update_ui_status("Already on SD");
return true;
return DL_EXISTED;
} else {
ESP_LOGI(TAG, "File exists but override=true, overwriting %s", path);
unlink(path);
@@ -141,7 +148,7 @@ static bool download_one_file(const char *url, const char *path) {
if (strlen(url) < 8 || strncmp(url, "http://", 7)!=0) {
update_ui_status("Invalid URL");
return false;
return DL_FAILED;
}
char tmp_path[520];
@@ -151,7 +158,7 @@ static bool download_one_file(const char *url, const char *path) {
if (!f) {
ESP_LOGE(TAG, "fopen fail %s errno=%d", tmp_path, errno);
update_ui_status("Failed to open file");
return false;
return DL_FAILED;
}
esp_http_client_config_t cfg = {
@@ -166,7 +173,7 @@ static bool download_one_file(const char *url, const char *path) {
fclose(f);
unlink(tmp_path);
update_ui_status("HTTP init failed");
return false;
return DL_FAILED;
}
esp_err_t err = esp_http_client_open(client, 0);
@@ -175,7 +182,7 @@ static bool download_one_file(const char *url, const char *path) {
fclose(f);
unlink(tmp_path);
update_ui_status("HTTP open failed");
return false;
return DL_FAILED;
}
int content_len = esp_http_client_fetch_headers(client);
@@ -189,7 +196,7 @@ static bool download_one_file(const char *url, const char *path) {
esp_http_client_cleanup(client);
fclose(f);
unlink(tmp_path);
return false;
return DL_FAILED;
}
G.expected = content_len;
@@ -203,7 +210,7 @@ static bool download_one_file(const char *url, const char *path) {
fclose(f);
unlink(tmp_path);
update_ui_status("No memory");
return false;
return DL_FAILED;
}
}
@@ -264,18 +271,19 @@ static bool download_one_file(const char *url, const char *path) {
esp_http_client_cleanup(client);
fclose(f);
if (G.cancel_req) { unlink(tmp_path); update_ui_status("Canceled"); return false; }
if (!ok || total < 512) { unlink(tmp_path); update_ui_status("Failed – error"); return false; }
if (content_len >=0 && total < content_len * 95 / 100) { unlink(tmp_path); update_ui_status("Failed – incomplete"); return false; }
if (rename(tmp_path, path) != 0) { unlink(tmp_path); update_ui_status("Rename failed"); return false; }
if (G.cancel_req) { unlink(tmp_path); update_ui_status("Canceled"); return DL_FAILED; }
if (!ok || total < 512) { unlink(tmp_path); update_ui_status("Failed – error"); return DL_FAILED; }
if (content_len >=0 && total < content_len * 95 / 100) { unlink(tmp_path); update_ui_status("Failed – incomplete"); return DL_FAILED; }
if (rename(tmp_path, path) != 0) { unlink(tmp_path); update_ui_status("Rename failed"); return DL_FAILED; }
return true;
return DL_DOWNLOADED;
}
static void download_task(void *arg) {
(void)arg;
G.downloading = true;
G.cancel_req = false;
G.task_exited = false;
G.last_pct = -1;
char url[512];
@@ -285,35 +293,48 @@ static void download_task(void *arg) {
url[sizeof(url)-1]=0;
path[sizeof(path)-1]=0;
bool ok = download_one_file(url, path);
if (ok) {
int dl_res = download_one_file(url, path);
if (dl_res == DL_DOWNLOADED || dl_res == DL_EXISTED) {
char msg[64];
snprintf(msg, sizeof(msg), "Done! %d KB", G.total/1024);
if (dl_res == DL_EXISTED) snprintf(msg, sizeof(msg), "Already on SD (%d KB)", G.total/1024);
else snprintf(msg, sizeof(msg), "Done! %d KB", G.total/1024);
update_ui_status(msg);
}
tt_lvgl_lock(portMAX_DELAY);
if (G.btn_cancel) {
lv_obj_t* lbl = lv_obj_get_child(G.btn_cancel, 0);
if (lbl) lv_label_set_text(lbl, "Close");
}
tt_lvgl_unlock();
G.downloading = false;
set_result_and_close(dl_res);
G.task_exited = true;
G.dl_handle = NULL;
set_result_and_close(ok);
vTaskDelete(NULL);
}
static void btn_cancel_cb(lv_event_t *e) {
(void)e;
ESP_LOGI(TAG, "btn_cancel_cb clicked! downloading=%d", G.downloading);
if (G.btn_cancel) {
lv_obj_remove_flag(G.btn_cancel, LV_OBJ_FLAG_CLICKABLE);
}
if (!G.downloading) {
tt_app_stop();
return;
}
G.cancel_req = true;
tt_lvgl_lock(portMAX_DELAY);
if (G.lbl_status) lv_label_set_text(G.lbl_status, "Canceling...");
tt_lvgl_unlock();
}
static void build_ui(void) {
tt_lvgl_lock(portMAX_DELAY);
lv_obj_t *root = lv_obj_create(lv_scr_act());
G.root_obj = root;
lv_obj_set_size(root, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_pad_all(root, 8, 0);
lv_obj_set_style_bg_color(root, lv_color_hex(0x111111), 0);
@@ -448,9 +469,31 @@ static void onHide(AppHandle app, void* data) {
(void)app; (void)data;
if (G.dl_handle) {
G.cancel_req = true;
for (int i=0;i<20 && G.dl_handle!=NULL; i++) vTaskDelay(pdMS_TO_TICKS(100));
if (G.dl_handle) { vTaskDelete(G.dl_handle); G.dl_handle = NULL; G.downloading = false; }
for (int i = 0; i < 30 && !G.task_exited; i++) {
vTaskDelay(pdMS_TO_TICKS(100));
}
if (!G.task_exited && G.dl_handle) {
ESP_LOGW(TAG, "onHide: force deleting dl task after timeout");
vTaskDelete(G.dl_handle);
G.dl_handle = NULL;
G.downloading = false;
}
vTaskDelay(pdMS_TO_TICKS(50));
}
tt_lvgl_lock(portMAX_DELAY);
if (G.root_obj) {
lv_obj_delete(G.root_obj);
G.root_obj = NULL;
G.lbl_url = NULL;
G.lbl_path = NULL;
G.lbl_pct = NULL;
G.lbl_detail = NULL;
G.lbl_status = NULL;
G.bar = NULL;
G.btn_cancel = NULL;
}
tt_lvgl_unlock();
}
int main(int argc, char* argv[]) {