feat: add HalStorage (#656)
## Summary Continue my changes to introduce the HAL infrastructure from https://github.com/crosspoint-reader/crosspoint-reader/pull/522 This PR touches quite a lot of files, but most of them are just name changing. It should not have any impacts to the end behavior. ## Additional Context My plan is to firstly add this small shim layer, which sounds useless at first, but then I'll implement an emulated driver which can be helpful for testing and for development. Currently, on my fork, I'm using a FS driver that allow "mounting" a local directory from my computer to the device, much like the `-v` mount option on docker. This allows me to quickly reset `.crosspoint` directory if anything goes wrong. I plan to upstream this feature when this PR get merged. --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? NO
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
#include "Epub.h"
|
#include "Epub.h"
|
||||||
|
|
||||||
#include <FsHelpers.h>
|
#include <FsHelpers.h>
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <JpegToBmpConverter.h>
|
#include <JpegToBmpConverter.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
#include <ZipFile.h>
|
#include <ZipFile.h>
|
||||||
|
|
||||||
#include "Epub/parsers/ContainerParser.h"
|
#include "Epub/parsers/ContainerParser.h"
|
||||||
@@ -105,12 +105,12 @@ bool Epub::parseTocNcxFile() const {
|
|||||||
|
|
||||||
const auto tmpNcxPath = getCachePath() + "/toc.ncx";
|
const auto tmpNcxPath = getCachePath() + "/toc.ncx";
|
||||||
FsFile tempNcxFile;
|
FsFile tempNcxFile;
|
||||||
if (!SdMan.openFileForWrite("EBP", tmpNcxPath, tempNcxFile)) {
|
if (!Storage.openFileForWrite("EBP", tmpNcxPath, tempNcxFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
readItemContentsToStream(tocNcxItem, tempNcxFile, 1024);
|
readItemContentsToStream(tocNcxItem, tempNcxFile, 1024);
|
||||||
tempNcxFile.close();
|
tempNcxFile.close();
|
||||||
if (!SdMan.openFileForRead("EBP", tmpNcxPath, tempNcxFile)) {
|
if (!Storage.openFileForRead("EBP", tmpNcxPath, tempNcxFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto ncxSize = tempNcxFile.size();
|
const auto ncxSize = tempNcxFile.size();
|
||||||
@@ -145,7 +145,7 @@ bool Epub::parseTocNcxFile() const {
|
|||||||
|
|
||||||
free(ncxBuffer);
|
free(ncxBuffer);
|
||||||
tempNcxFile.close();
|
tempNcxFile.close();
|
||||||
SdMan.remove(tmpNcxPath.c_str());
|
Storage.remove(tmpNcxPath.c_str());
|
||||||
|
|
||||||
Serial.printf("[%lu] [EBP] Parsed TOC items\n", millis());
|
Serial.printf("[%lu] [EBP] Parsed TOC items\n", millis());
|
||||||
return true;
|
return true;
|
||||||
@@ -162,12 +162,12 @@ bool Epub::parseTocNavFile() const {
|
|||||||
|
|
||||||
const auto tmpNavPath = getCachePath() + "/toc.nav";
|
const auto tmpNavPath = getCachePath() + "/toc.nav";
|
||||||
FsFile tempNavFile;
|
FsFile tempNavFile;
|
||||||
if (!SdMan.openFileForWrite("EBP", tmpNavPath, tempNavFile)) {
|
if (!Storage.openFileForWrite("EBP", tmpNavPath, tempNavFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
readItemContentsToStream(tocNavItem, tempNavFile, 1024);
|
readItemContentsToStream(tocNavItem, tempNavFile, 1024);
|
||||||
tempNavFile.close();
|
tempNavFile.close();
|
||||||
if (!SdMan.openFileForRead("EBP", tmpNavPath, tempNavFile)) {
|
if (!Storage.openFileForRead("EBP", tmpNavPath, tempNavFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto navSize = tempNavFile.size();
|
const auto navSize = tempNavFile.size();
|
||||||
@@ -202,7 +202,7 @@ bool Epub::parseTocNavFile() const {
|
|||||||
|
|
||||||
free(navBuffer);
|
free(navBuffer);
|
||||||
tempNavFile.close();
|
tempNavFile.close();
|
||||||
SdMan.remove(tmpNavPath.c_str());
|
Storage.remove(tmpNavPath.c_str());
|
||||||
|
|
||||||
Serial.printf("[%lu] [EBP] Parsed TOC nav items\n", millis());
|
Serial.printf("[%lu] [EBP] Parsed TOC nav items\n", millis());
|
||||||
return true;
|
return true;
|
||||||
@@ -212,7 +212,7 @@ std::string Epub::getCssRulesCache() const { return cachePath + "/css_rules.cach
|
|||||||
|
|
||||||
bool Epub::loadCssRulesFromCache() const {
|
bool Epub::loadCssRulesFromCache() const {
|
||||||
FsFile cssCacheFile;
|
FsFile cssCacheFile;
|
||||||
if (SdMan.openFileForRead("EBP", getCssRulesCache(), cssCacheFile)) {
|
if (Storage.openFileForRead("EBP", getCssRulesCache(), cssCacheFile)) {
|
||||||
if (cssParser->loadFromCache(cssCacheFile)) {
|
if (cssParser->loadFromCache(cssCacheFile)) {
|
||||||
cssCacheFile.close();
|
cssCacheFile.close();
|
||||||
Serial.printf("[%lu] [EBP] Loaded CSS rules from cache\n", millis());
|
Serial.printf("[%lu] [EBP] Loaded CSS rules from cache\n", millis());
|
||||||
@@ -238,32 +238,32 @@ void Epub::parseCssFiles() const {
|
|||||||
// Extract CSS file to temp location
|
// Extract CSS file to temp location
|
||||||
const auto tmpCssPath = getCachePath() + "/.tmp.css";
|
const auto tmpCssPath = getCachePath() + "/.tmp.css";
|
||||||
FsFile tempCssFile;
|
FsFile tempCssFile;
|
||||||
if (!SdMan.openFileForWrite("EBP", tmpCssPath, tempCssFile)) {
|
if (!Storage.openFileForWrite("EBP", tmpCssPath, tempCssFile)) {
|
||||||
Serial.printf("[%lu] [EBP] Could not create temp CSS file\n", millis());
|
Serial.printf("[%lu] [EBP] Could not create temp CSS file\n", millis());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!readItemContentsToStream(cssPath, tempCssFile, 1024)) {
|
if (!readItemContentsToStream(cssPath, tempCssFile, 1024)) {
|
||||||
Serial.printf("[%lu] [EBP] Could not read CSS file: %s\n", millis(), cssPath.c_str());
|
Serial.printf("[%lu] [EBP] Could not read CSS file: %s\n", millis(), cssPath.c_str());
|
||||||
tempCssFile.close();
|
tempCssFile.close();
|
||||||
SdMan.remove(tmpCssPath.c_str());
|
Storage.remove(tmpCssPath.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tempCssFile.close();
|
tempCssFile.close();
|
||||||
|
|
||||||
// Parse the CSS file
|
// Parse the CSS file
|
||||||
if (!SdMan.openFileForRead("EBP", tmpCssPath, tempCssFile)) {
|
if (!Storage.openFileForRead("EBP", tmpCssPath, tempCssFile)) {
|
||||||
Serial.printf("[%lu] [EBP] Could not open temp CSS file for reading\n", millis());
|
Serial.printf("[%lu] [EBP] Could not open temp CSS file for reading\n", millis());
|
||||||
SdMan.remove(tmpCssPath.c_str());
|
Storage.remove(tmpCssPath.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cssParser->loadFromStream(tempCssFile);
|
cssParser->loadFromStream(tempCssFile);
|
||||||
tempCssFile.close();
|
tempCssFile.close();
|
||||||
SdMan.remove(tmpCssPath.c_str());
|
Storage.remove(tmpCssPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save to cache for next time
|
// Save to cache for next time
|
||||||
FsFile cssCacheFile;
|
FsFile cssCacheFile;
|
||||||
if (SdMan.openFileForWrite("EBP", getCssRulesCache(), cssCacheFile)) {
|
if (Storage.openFileForWrite("EBP", getCssRulesCache(), cssCacheFile)) {
|
||||||
cssParser->saveToCache(cssCacheFile);
|
cssParser->saveToCache(cssCacheFile);
|
||||||
cssCacheFile.close();
|
cssCacheFile.close();
|
||||||
}
|
}
|
||||||
@@ -399,12 +399,12 @@ bool Epub::load(const bool buildIfMissing, const bool skipLoadingCss) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Epub::clearCache() const {
|
bool Epub::clearCache() const {
|
||||||
if (!SdMan.exists(cachePath.c_str())) {
|
if (!Storage.exists(cachePath.c_str())) {
|
||||||
Serial.printf("[%lu] [EPB] Cache does not exist, no action needed\n", millis());
|
Serial.printf("[%lu] [EPB] Cache does not exist, no action needed\n", millis());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.removeDir(cachePath.c_str())) {
|
if (!Storage.removeDir(cachePath.c_str())) {
|
||||||
Serial.printf("[%lu] [EPB] Failed to clear cache\n", millis());
|
Serial.printf("[%lu] [EPB] Failed to clear cache\n", millis());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -414,11 +414,11 @@ bool Epub::clearCache() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Epub::setupCacheDir() const {
|
void Epub::setupCacheDir() const {
|
||||||
if (SdMan.exists(cachePath.c_str())) {
|
if (Storage.exists(cachePath.c_str())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SdMan.mkdir(cachePath.c_str());
|
Storage.mkdir(cachePath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& Epub::getCachePath() const { return cachePath; }
|
const std::string& Epub::getCachePath() const { return cachePath; }
|
||||||
@@ -459,7 +459,7 @@ std::string Epub::getCoverBmpPath(bool cropped) const {
|
|||||||
|
|
||||||
bool Epub::generateCoverBmp(bool cropped) const {
|
bool Epub::generateCoverBmp(bool cropped) const {
|
||||||
// Already generated, return true
|
// Already generated, return true
|
||||||
if (SdMan.exists(getCoverBmpPath(cropped).c_str())) {
|
if (Storage.exists(getCoverBmpPath(cropped).c_str())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,29 +480,29 @@ bool Epub::generateCoverBmp(bool cropped) const {
|
|||||||
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
|
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
|
||||||
|
|
||||||
FsFile coverJpg;
|
FsFile coverJpg;
|
||||||
if (!SdMan.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) {
|
if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
readItemContentsToStream(coverImageHref, coverJpg, 1024);
|
readItemContentsToStream(coverImageHref, coverJpg, 1024);
|
||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
|
|
||||||
if (!SdMan.openFileForRead("EBP", coverJpgTempPath, coverJpg)) {
|
if (!Storage.openFileForRead("EBP", coverJpgTempPath, coverJpg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile coverBmp;
|
FsFile coverBmp;
|
||||||
if (!SdMan.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) {
|
if (!Storage.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) {
|
||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const bool success = JpegToBmpConverter::jpegFileToBmpStream(coverJpg, coverBmp, cropped);
|
const bool success = JpegToBmpConverter::jpegFileToBmpStream(coverJpg, coverBmp, cropped);
|
||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
coverBmp.close();
|
coverBmp.close();
|
||||||
SdMan.remove(coverJpgTempPath.c_str());
|
Storage.remove(coverJpgTempPath.c_str());
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Serial.printf("[%lu] [EBP] Failed to generate BMP from JPG cover image\n", millis());
|
Serial.printf("[%lu] [EBP] Failed to generate BMP from JPG cover image\n", millis());
|
||||||
SdMan.remove(getCoverBmpPath(cropped).c_str());
|
Storage.remove(getCoverBmpPath(cropped).c_str());
|
||||||
}
|
}
|
||||||
Serial.printf("[%lu] [EBP] Generated BMP from JPG cover image, success: %s\n", millis(), success ? "yes" : "no");
|
Serial.printf("[%lu] [EBP] Generated BMP from JPG cover image, success: %s\n", millis(), success ? "yes" : "no");
|
||||||
return success;
|
return success;
|
||||||
@@ -518,7 +518,7 @@ std::string Epub::getThumbBmpPath(int height) const { return cachePath + "/thumb
|
|||||||
|
|
||||||
bool Epub::generateThumbBmp(int height) const {
|
bool Epub::generateThumbBmp(int height) const {
|
||||||
// Already generated, return true
|
// Already generated, return true
|
||||||
if (SdMan.exists(getThumbBmpPath(height).c_str())) {
|
if (Storage.exists(getThumbBmpPath(height).c_str())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,18 +536,18 @@ bool Epub::generateThumbBmp(int height) const {
|
|||||||
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
|
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
|
||||||
|
|
||||||
FsFile coverJpg;
|
FsFile coverJpg;
|
||||||
if (!SdMan.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) {
|
if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
readItemContentsToStream(coverImageHref, coverJpg, 1024);
|
readItemContentsToStream(coverImageHref, coverJpg, 1024);
|
||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
|
|
||||||
if (!SdMan.openFileForRead("EBP", coverJpgTempPath, coverJpg)) {
|
if (!Storage.openFileForRead("EBP", coverJpgTempPath, coverJpg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile thumbBmp;
|
FsFile thumbBmp;
|
||||||
if (!SdMan.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp)) {
|
if (!Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp)) {
|
||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -559,11 +559,11 @@ bool Epub::generateThumbBmp(int height) const {
|
|||||||
THUMB_TARGET_HEIGHT);
|
THUMB_TARGET_HEIGHT);
|
||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
thumbBmp.close();
|
thumbBmp.close();
|
||||||
SdMan.remove(coverJpgTempPath.c_str());
|
Storage.remove(coverJpgTempPath.c_str());
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Serial.printf("[%lu] [EBP] Failed to generate thumb BMP from JPG cover image\n", millis());
|
Serial.printf("[%lu] [EBP] Failed to generate thumb BMP from JPG cover image\n", millis());
|
||||||
SdMan.remove(getThumbBmpPath(height).c_str());
|
Storage.remove(getThumbBmpPath(height).c_str());
|
||||||
}
|
}
|
||||||
Serial.printf("[%lu] [EBP] Generated thumb BMP from JPG cover image, success: %s\n", millis(),
|
Serial.printf("[%lu] [EBP] Generated thumb BMP from JPG cover image, success: %s\n", millis(),
|
||||||
success ? "yes" : "no");
|
success ? "yes" : "no");
|
||||||
@@ -574,7 +574,7 @@ bool Epub::generateThumbBmp(int height) const {
|
|||||||
|
|
||||||
// Write an empty bmp file to avoid generation attempts in the future
|
// Write an empty bmp file to avoid generation attempts in the future
|
||||||
FsFile thumbBmp;
|
FsFile thumbBmp;
|
||||||
SdMan.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp);
|
Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp);
|
||||||
thumbBmp.close();
|
thumbBmp.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ bool BookMetadataCache::beginContentOpfPass() {
|
|||||||
Serial.printf("[%lu] [BMC] Beginning content opf pass\n", millis());
|
Serial.printf("[%lu] [BMC] Beginning content opf pass\n", millis());
|
||||||
|
|
||||||
// Open spine file for writing
|
// Open spine file for writing
|
||||||
return SdMan.openFileForWrite("BMC", cachePath + tmpSpineBinFile, spineFile);
|
return Storage.openFileForWrite("BMC", cachePath + tmpSpineBinFile, spineFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BookMetadataCache::endContentOpfPass() {
|
bool BookMetadataCache::endContentOpfPass() {
|
||||||
@@ -40,10 +40,10 @@ bool BookMetadataCache::endContentOpfPass() {
|
|||||||
bool BookMetadataCache::beginTocPass() {
|
bool BookMetadataCache::beginTocPass() {
|
||||||
Serial.printf("[%lu] [BMC] Beginning toc pass\n", millis());
|
Serial.printf("[%lu] [BMC] Beginning toc pass\n", millis());
|
||||||
|
|
||||||
if (!SdMan.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) {
|
if (!Storage.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!SdMan.openFileForWrite("BMC", cachePath + tmpTocBinFile, tocFile)) {
|
if (!Storage.openFileForWrite("BMC", cachePath + tmpTocBinFile, tocFile)) {
|
||||||
spineFile.close();
|
spineFile.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -98,16 +98,16 @@ bool BookMetadataCache::endWrite() {
|
|||||||
|
|
||||||
bool BookMetadataCache::buildBookBin(const std::string& epubPath, const BookMetadata& metadata) {
|
bool BookMetadataCache::buildBookBin(const std::string& epubPath, const BookMetadata& metadata) {
|
||||||
// Open all three files, writing to meta, reading from spine and toc
|
// Open all three files, writing to meta, reading from spine and toc
|
||||||
if (!SdMan.openFileForWrite("BMC", cachePath + bookBinFile, bookFile)) {
|
if (!Storage.openFileForWrite("BMC", cachePath + bookBinFile, bookFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) {
|
if (!Storage.openFileForRead("BMC", cachePath + tmpSpineBinFile, spineFile)) {
|
||||||
bookFile.close();
|
bookFile.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.openFileForRead("BMC", cachePath + tmpTocBinFile, tocFile)) {
|
if (!Storage.openFileForRead("BMC", cachePath + tmpTocBinFile, tocFile)) {
|
||||||
bookFile.close();
|
bookFile.close();
|
||||||
spineFile.close();
|
spineFile.close();
|
||||||
return false;
|
return false;
|
||||||
@@ -275,11 +275,11 @@ bool BookMetadataCache::buildBookBin(const std::string& epubPath, const BookMeta
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BookMetadataCache::cleanupTmpFiles() const {
|
bool BookMetadataCache::cleanupTmpFiles() const {
|
||||||
if (SdMan.exists((cachePath + tmpSpineBinFile).c_str())) {
|
if (Storage.exists((cachePath + tmpSpineBinFile).c_str())) {
|
||||||
SdMan.remove((cachePath + tmpSpineBinFile).c_str());
|
Storage.remove((cachePath + tmpSpineBinFile).c_str());
|
||||||
}
|
}
|
||||||
if (SdMan.exists((cachePath + tmpTocBinFile).c_str())) {
|
if (Storage.exists((cachePath + tmpTocBinFile).c_str())) {
|
||||||
SdMan.remove((cachePath + tmpTocBinFile).c_str());
|
Storage.remove((cachePath + tmpTocBinFile).c_str());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -364,7 +364,7 @@ void BookMetadataCache::createTocEntry(const std::string& title, const std::stri
|
|||||||
/* ============= READING / LOADING FUNCTIONS ================ */
|
/* ============= READING / LOADING FUNCTIONS ================ */
|
||||||
|
|
||||||
bool BookMetadataCache::load() {
|
bool BookMetadataCache::load() {
|
||||||
if (!SdMan.openFileForRead("BMC", cachePath + bookBinFile, bookFile)) {
|
if (!Storage.openFileForRead("BMC", cachePath + bookBinFile, bookFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SdFat.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "Section.h"
|
#include "Section.h"
|
||||||
|
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
#include <Serialization.h>
|
#include <Serialization.h>
|
||||||
|
|
||||||
#include "Page.h"
|
#include "Page.h"
|
||||||
@@ -60,7 +60,7 @@ void Section::writeSectionFileHeader(const int fontId, const float lineCompressi
|
|||||||
bool Section::loadSectionFile(const int fontId, const float lineCompression, const bool extraParagraphSpacing,
|
bool Section::loadSectionFile(const int fontId, const float lineCompression, const bool extraParagraphSpacing,
|
||||||
const uint8_t paragraphAlignment, const uint16_t viewportWidth,
|
const uint8_t paragraphAlignment, const uint16_t viewportWidth,
|
||||||
const uint16_t viewportHeight, const bool hyphenationEnabled, const bool embeddedStyle) {
|
const uint16_t viewportHeight, const bool hyphenationEnabled, const bool embeddedStyle) {
|
||||||
if (!SdMan.openFileForRead("SCT", filePath, file)) {
|
if (!Storage.openFileForRead("SCT", filePath, file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,12 +110,12 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con
|
|||||||
|
|
||||||
// Your updated class method (assuming you are using the 'SD' object, which is a wrapper for a specific filesystem)
|
// Your updated class method (assuming you are using the 'SD' object, which is a wrapper for a specific filesystem)
|
||||||
bool Section::clearCache() const {
|
bool Section::clearCache() const {
|
||||||
if (!SdMan.exists(filePath.c_str())) {
|
if (!Storage.exists(filePath.c_str())) {
|
||||||
Serial.printf("[%lu] [SCT] Cache does not exist, no action needed\n", millis());
|
Serial.printf("[%lu] [SCT] Cache does not exist, no action needed\n", millis());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.remove(filePath.c_str())) {
|
if (!Storage.remove(filePath.c_str())) {
|
||||||
Serial.printf("[%lu] [SCT] Failed to clear cache\n", millis());
|
Serial.printf("[%lu] [SCT] Failed to clear cache\n", millis());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
|
|||||||
// Create cache directory if it doesn't exist
|
// Create cache directory if it doesn't exist
|
||||||
{
|
{
|
||||||
const auto sectionsDir = epub->getCachePath() + "/sections";
|
const auto sectionsDir = epub->getCachePath() + "/sections";
|
||||||
SdMan.mkdir(sectionsDir.c_str());
|
Storage.mkdir(sectionsDir.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retry logic for SD card timing issues
|
// Retry logic for SD card timing issues
|
||||||
@@ -147,12 +147,12 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove any incomplete file from previous attempt before retrying
|
// Remove any incomplete file from previous attempt before retrying
|
||||||
if (SdMan.exists(tmpHtmlPath.c_str())) {
|
if (Storage.exists(tmpHtmlPath.c_str())) {
|
||||||
SdMan.remove(tmpHtmlPath.c_str());
|
Storage.remove(tmpHtmlPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile tmpHtml;
|
FsFile tmpHtml;
|
||||||
if (!SdMan.openFileForWrite("SCT", tmpHtmlPath, tmpHtml)) {
|
if (!Storage.openFileForWrite("SCT", tmpHtmlPath, tmpHtml)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
success = epub->readItemContentsToStream(localPath, tmpHtml, 1024);
|
success = epub->readItemContentsToStream(localPath, tmpHtml, 1024);
|
||||||
@@ -160,8 +160,8 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
|
|||||||
tmpHtml.close();
|
tmpHtml.close();
|
||||||
|
|
||||||
// If streaming failed, remove the incomplete file immediately
|
// If streaming failed, remove the incomplete file immediately
|
||||||
if (!success && SdMan.exists(tmpHtmlPath.c_str())) {
|
if (!success && Storage.exists(tmpHtmlPath.c_str())) {
|
||||||
SdMan.remove(tmpHtmlPath.c_str());
|
Storage.remove(tmpHtmlPath.c_str());
|
||||||
Serial.printf("[%lu] [SCT] Removed incomplete temp file after failed attempt\n", millis());
|
Serial.printf("[%lu] [SCT] Removed incomplete temp file after failed attempt\n", millis());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,7 +173,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
|
|||||||
|
|
||||||
Serial.printf("[%lu] [SCT] Streamed temp HTML to %s (%d bytes)\n", millis(), tmpHtmlPath.c_str(), fileSize);
|
Serial.printf("[%lu] [SCT] Streamed temp HTML to %s (%d bytes)\n", millis(), tmpHtmlPath.c_str(), fileSize);
|
||||||
|
|
||||||
if (!SdMan.openFileForWrite("SCT", filePath, file)) {
|
if (!Storage.openFileForWrite("SCT", filePath, file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
writeSectionFileHeader(fontId, lineCompression, extraParagraphSpacing, paragraphAlignment, viewportWidth,
|
writeSectionFileHeader(fontId, lineCompression, extraParagraphSpacing, paragraphAlignment, viewportWidth,
|
||||||
@@ -188,11 +188,11 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
|
|||||||
Hyphenator::setPreferredLanguage(epub->getLanguage());
|
Hyphenator::setPreferredLanguage(epub->getLanguage());
|
||||||
success = visitor.parseAndBuildPages();
|
success = visitor.parseAndBuildPages();
|
||||||
|
|
||||||
SdMan.remove(tmpHtmlPath.c_str());
|
Storage.remove(tmpHtmlPath.c_str());
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Serial.printf("[%lu] [SCT] Failed to parse XML and build pages\n", millis());
|
Serial.printf("[%lu] [SCT] Failed to parse XML and build pages\n", millis());
|
||||||
file.close();
|
file.close();
|
||||||
SdMan.remove(filePath.c_str());
|
Storage.remove(filePath.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
|
|||||||
if (hasFailedLutRecords) {
|
if (hasFailedLutRecords) {
|
||||||
Serial.printf("[%lu] [SCT] Failed to write LUT due to invalid page positions\n", millis());
|
Serial.printf("[%lu] [SCT] Failed to write LUT due to invalid page positions\n", millis());
|
||||||
file.close();
|
file.close();
|
||||||
SdMan.remove(filePath.c_str());
|
Storage.remove(filePath.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Page> Section::loadPageFromSectionFile() {
|
std::unique_ptr<Page> Section::loadPageFromSectionFile() {
|
||||||
if (!SdMan.openFileForRead("SCT", filePath, file)) {
|
if (!Storage.openFileForRead("SCT", filePath, file)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <EpdFontFamily.h>
|
#include <EpdFontFamily.h>
|
||||||
#include <SdFat.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SdFat.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "ChapterHtmlSlimParser.h"
|
#include "ChapterHtmlSlimParser.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
#include <expat.h>
|
#include <expat.h>
|
||||||
|
|
||||||
#include "../Page.h"
|
#include "../Page.h"
|
||||||
@@ -482,7 +482,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForRead("EHP", filepath, file)) {
|
if (!Storage.openFileForRead("EHP", filepath, file)) {
|
||||||
XML_ParserFree(parser);
|
XML_ParserFree(parser);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ ContentOpfParser::~ContentOpfParser() {
|
|||||||
if (tempItemStore) {
|
if (tempItemStore) {
|
||||||
tempItemStore.close();
|
tempItemStore.close();
|
||||||
}
|
}
|
||||||
if (SdMan.exists((cachePath + itemCacheFile).c_str())) {
|
if (Storage.exists((cachePath + itemCacheFile).c_str())) {
|
||||||
SdMan.remove((cachePath + itemCacheFile).c_str());
|
Storage.remove((cachePath + itemCacheFile).c_str());
|
||||||
}
|
}
|
||||||
itemIndex.clear();
|
itemIndex.clear();
|
||||||
itemIndex.shrink_to_fit();
|
itemIndex.shrink_to_fit();
|
||||||
@@ -118,7 +118,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
|
|||||||
|
|
||||||
if (self->state == IN_PACKAGE && (strcmp(name, "manifest") == 0 || strcmp(name, "opf:manifest") == 0)) {
|
if (self->state == IN_PACKAGE && (strcmp(name, "manifest") == 0 || strcmp(name, "opf:manifest") == 0)) {
|
||||||
self->state = IN_MANIFEST;
|
self->state = IN_MANIFEST;
|
||||||
if (!SdMan.openFileForWrite("COF", self->cachePath + itemCacheFile, self->tempItemStore)) {
|
if (!Storage.openFileForWrite("COF", self->cachePath + itemCacheFile, self->tempItemStore)) {
|
||||||
Serial.printf(
|
Serial.printf(
|
||||||
"[%lu] [COF] Couldn't open temp items file for writing. This is probably going to be a fatal error.\n",
|
"[%lu] [COF] Couldn't open temp items file for writing. This is probably going to be a fatal error.\n",
|
||||||
millis());
|
millis());
|
||||||
@@ -128,7 +128,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
|
|||||||
|
|
||||||
if (self->state == IN_PACKAGE && (strcmp(name, "spine") == 0 || strcmp(name, "opf:spine") == 0)) {
|
if (self->state == IN_PACKAGE && (strcmp(name, "spine") == 0 || strcmp(name, "opf:spine") == 0)) {
|
||||||
self->state = IN_SPINE;
|
self->state = IN_SPINE;
|
||||||
if (!SdMan.openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) {
|
if (!Storage.openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) {
|
||||||
Serial.printf(
|
Serial.printf(
|
||||||
"[%lu] [COF] Couldn't open temp items file for reading. This is probably going to be a fatal error.\n",
|
"[%lu] [COF] Couldn't open temp items file for reading. This is probably going to be a fatal error.\n",
|
||||||
millis());
|
millis());
|
||||||
@@ -149,7 +149,7 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
|
|||||||
self->state = IN_GUIDE;
|
self->state = IN_GUIDE;
|
||||||
// TODO Remove print
|
// TODO Remove print
|
||||||
Serial.printf("[%lu] [COF] Entering guide state.\n", millis());
|
Serial.printf("[%lu] [COF] Entering guide state.\n", millis());
|
||||||
if (!SdMan.openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) {
|
if (!Storage.openFileForRead("COF", self->cachePath + itemCacheFile, self->tempItemStore)) {
|
||||||
Serial.printf(
|
Serial.printf(
|
||||||
"[%lu] [COF] Couldn't open temp items file for reading. This is probably going to be a fatal error.\n",
|
"[%lu] [COF] Couldn't open temp items file for reading. This is probably going to be a fatal error.\n",
|
||||||
millis());
|
millis());
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SdFat.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "JpegToBmpConverter.h"
|
#include "JpegToBmpConverter.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SdFat.h>
|
|
||||||
#include <picojpeg.h>
|
#include <picojpeg.h>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "KOReaderCredentialStore.h"
|
#include "KOReaderCredentialStore.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <MD5Builder.h>
|
#include <MD5Builder.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
#include <Serialization.h>
|
#include <Serialization.h>
|
||||||
|
|
||||||
// Initialize the static instance
|
// Initialize the static instance
|
||||||
@@ -32,10 +32,10 @@ void KOReaderCredentialStore::obfuscate(std::string& data) const {
|
|||||||
|
|
||||||
bool KOReaderCredentialStore::saveToFile() const {
|
bool KOReaderCredentialStore::saveToFile() const {
|
||||||
// Make sure the directory exists
|
// Make sure the directory exists
|
||||||
SdMan.mkdir("/.crosspoint");
|
Storage.mkdir("/.crosspoint");
|
||||||
|
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForWrite("KRS", KOREADER_FILE, file)) {
|
if (!Storage.openFileForWrite("KRS", KOREADER_FILE, file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ bool KOReaderCredentialStore::saveToFile() const {
|
|||||||
|
|
||||||
bool KOReaderCredentialStore::loadFromFile() {
|
bool KOReaderCredentialStore::loadFromFile() {
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForRead("KRS", KOREADER_FILE, file)) {
|
if (!Storage.openFileForRead("KRS", KOREADER_FILE, file)) {
|
||||||
Serial.printf("[%lu] [KRS] No credentials file found\n", millis());
|
Serial.printf("[%lu] [KRS] No credentials file found\n", millis());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "KOReaderDocumentId.h"
|
#include "KOReaderDocumentId.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <MD5Builder.h>
|
#include <MD5Builder.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Extract filename from path (everything after last '/')
|
// Extract filename from path (everything after last '/')
|
||||||
@@ -43,7 +43,7 @@ size_t KOReaderDocumentId::getOffset(int i) {
|
|||||||
|
|
||||||
std::string KOReaderDocumentId::calculate(const std::string& filePath) {
|
std::string KOReaderDocumentId::calculate(const std::string& filePath) {
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForRead("KODoc", filePath, file)) {
|
if (!Storage.openFileForRead("KODoc", filePath, file)) {
|
||||||
Serial.printf("[%lu] [KODoc] Failed to open file: %s\n", millis(), filePath.c_str());
|
Serial.printf("[%lu] [KODoc] Failed to open file: %s\n", millis(), filePath.c_str());
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SdFat.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ bool Txt::load() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.exists(filepath.c_str())) {
|
if (!Storage.exists(filepath.c_str())) {
|
||||||
Serial.printf("[%lu] [TXT] File does not exist: %s\n", millis(), filepath.c_str());
|
Serial.printf("[%lu] [TXT] File does not exist: %s\n", millis(), filepath.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForRead("TXT", filepath, file)) {
|
if (!Storage.openFileForRead("TXT", filepath, file)) {
|
||||||
Serial.printf("[%lu] [TXT] Failed to open file: %s\n", millis(), filepath.c_str());
|
Serial.printf("[%lu] [TXT] Failed to open file: %s\n", millis(), filepath.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -48,11 +48,11 @@ std::string Txt::getTitle() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Txt::setupCacheDir() const {
|
void Txt::setupCacheDir() const {
|
||||||
if (!SdMan.exists(cacheBasePath.c_str())) {
|
if (!Storage.exists(cacheBasePath.c_str())) {
|
||||||
SdMan.mkdir(cacheBasePath.c_str());
|
Storage.mkdir(cacheBasePath.c_str());
|
||||||
}
|
}
|
||||||
if (!SdMan.exists(cachePath.c_str())) {
|
if (!Storage.exists(cachePath.c_str())) {
|
||||||
SdMan.mkdir(cachePath.c_str());
|
Storage.mkdir(cachePath.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ std::string Txt::findCoverImage() const {
|
|||||||
// First priority: look for image with same name as txt file (e.g., mybook.jpg)
|
// First priority: look for image with same name as txt file (e.g., mybook.jpg)
|
||||||
for (const auto& ext : extensions) {
|
for (const auto& ext : extensions) {
|
||||||
std::string coverPath = folder + "/" + baseName + ext;
|
std::string coverPath = folder + "/" + baseName + ext;
|
||||||
if (SdMan.exists(coverPath.c_str())) {
|
if (Storage.exists(coverPath.c_str())) {
|
||||||
Serial.printf("[%lu] [TXT] Found matching cover image: %s\n", millis(), coverPath.c_str());
|
Serial.printf("[%lu] [TXT] Found matching cover image: %s\n", millis(), coverPath.c_str());
|
||||||
return coverPath;
|
return coverPath;
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ std::string Txt::findCoverImage() const {
|
|||||||
for (const auto& name : coverNames) {
|
for (const auto& name : coverNames) {
|
||||||
for (const auto& ext : extensions) {
|
for (const auto& ext : extensions) {
|
||||||
std::string coverPath = folder + "/" + std::string(name) + ext;
|
std::string coverPath = folder + "/" + std::string(name) + ext;
|
||||||
if (SdMan.exists(coverPath.c_str())) {
|
if (Storage.exists(coverPath.c_str())) {
|
||||||
Serial.printf("[%lu] [TXT] Found fallback cover image: %s\n", millis(), coverPath.c_str());
|
Serial.printf("[%lu] [TXT] Found fallback cover image: %s\n", millis(), coverPath.c_str());
|
||||||
return coverPath;
|
return coverPath;
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ std::string Txt::getCoverBmpPath() const { return cachePath + "/cover.bmp"; }
|
|||||||
|
|
||||||
bool Txt::generateCoverBmp() const {
|
bool Txt::generateCoverBmp() const {
|
||||||
// Already generated, return true
|
// Already generated, return true
|
||||||
if (SdMan.exists(getCoverBmpPath().c_str())) {
|
if (Storage.exists(getCoverBmpPath().c_str())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,10 +122,10 @@ bool Txt::generateCoverBmp() const {
|
|||||||
// Copy BMP file to cache
|
// Copy BMP file to cache
|
||||||
Serial.printf("[%lu] [TXT] Copying BMP cover image to cache\n", millis());
|
Serial.printf("[%lu] [TXT] Copying BMP cover image to cache\n", millis());
|
||||||
FsFile src, dst;
|
FsFile src, dst;
|
||||||
if (!SdMan.openFileForRead("TXT", coverImagePath, src)) {
|
if (!Storage.openFileForRead("TXT", coverImagePath, src)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!SdMan.openFileForWrite("TXT", getCoverBmpPath(), dst)) {
|
if (!Storage.openFileForWrite("TXT", getCoverBmpPath(), dst)) {
|
||||||
src.close();
|
src.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -144,10 +144,10 @@ bool Txt::generateCoverBmp() const {
|
|||||||
// Convert JPG/JPEG to BMP (same approach as Epub)
|
// Convert JPG/JPEG to BMP (same approach as Epub)
|
||||||
Serial.printf("[%lu] [TXT] Generating BMP from JPG cover image\n", millis());
|
Serial.printf("[%lu] [TXT] Generating BMP from JPG cover image\n", millis());
|
||||||
FsFile coverJpg, coverBmp;
|
FsFile coverJpg, coverBmp;
|
||||||
if (!SdMan.openFileForRead("TXT", coverImagePath, coverJpg)) {
|
if (!Storage.openFileForRead("TXT", coverImagePath, coverJpg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!SdMan.openFileForWrite("TXT", getCoverBmpPath(), coverBmp)) {
|
if (!Storage.openFileForWrite("TXT", getCoverBmpPath(), coverBmp)) {
|
||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ bool Txt::generateCoverBmp() const {
|
|||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Serial.printf("[%lu] [TXT] Failed to generate BMP from JPG cover image\n", millis());
|
Serial.printf("[%lu] [TXT] Failed to generate BMP from JPG cover image\n", millis());
|
||||||
SdMan.remove(getCoverBmpPath().c_str());
|
Storage.remove(getCoverBmpPath().c_str());
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("[%lu] [TXT] Generated BMP from JPG cover image\n", millis());
|
Serial.printf("[%lu] [TXT] Generated BMP from JPG cover image\n", millis());
|
||||||
}
|
}
|
||||||
@@ -175,7 +175,7 @@ bool Txt::readContent(uint8_t* buffer, size_t offset, size_t length) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForRead("TXT", filepath, file)) {
|
if (!Storage.openFileForRead("TXT", filepath, file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
#include "Xtc.h"
|
#include "Xtc.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
|
|
||||||
bool Xtc::load() {
|
bool Xtc::load() {
|
||||||
Serial.printf("[%lu] [XTC] Loading XTC: %s\n", millis(), filepath.c_str());
|
Serial.printf("[%lu] [XTC] Loading XTC: %s\n", millis(), filepath.c_str());
|
||||||
@@ -30,12 +30,12 @@ bool Xtc::load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Xtc::clearCache() const {
|
bool Xtc::clearCache() const {
|
||||||
if (!SdMan.exists(cachePath.c_str())) {
|
if (!Storage.exists(cachePath.c_str())) {
|
||||||
Serial.printf("[%lu] [XTC] Cache does not exist, no action needed\n", millis());
|
Serial.printf("[%lu] [XTC] Cache does not exist, no action needed\n", millis());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.removeDir(cachePath.c_str())) {
|
if (!Storage.removeDir(cachePath.c_str())) {
|
||||||
Serial.printf("[%lu] [XTC] Failed to clear cache\n", millis());
|
Serial.printf("[%lu] [XTC] Failed to clear cache\n", millis());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -45,17 +45,17 @@ bool Xtc::clearCache() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Xtc::setupCacheDir() const {
|
void Xtc::setupCacheDir() const {
|
||||||
if (SdMan.exists(cachePath.c_str())) {
|
if (Storage.exists(cachePath.c_str())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create directories recursively
|
// Create directories recursively
|
||||||
for (size_t i = 1; i < cachePath.length(); i++) {
|
for (size_t i = 1; i < cachePath.length(); i++) {
|
||||||
if (cachePath[i] == '/') {
|
if (cachePath[i] == '/') {
|
||||||
SdMan.mkdir(cachePath.substr(0, i).c_str());
|
Storage.mkdir(cachePath.substr(0, i).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SdMan.mkdir(cachePath.c_str());
|
Storage.mkdir(cachePath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Xtc::getTitle() const {
|
std::string Xtc::getTitle() const {
|
||||||
@@ -114,7 +114,7 @@ std::string Xtc::getCoverBmpPath() const { return cachePath + "/cover.bmp"; }
|
|||||||
|
|
||||||
bool Xtc::generateCoverBmp() const {
|
bool Xtc::generateCoverBmp() const {
|
||||||
// Already generated
|
// Already generated
|
||||||
if (SdMan.exists(getCoverBmpPath().c_str())) {
|
if (Storage.exists(getCoverBmpPath().c_str())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ bool Xtc::generateCoverBmp() const {
|
|||||||
|
|
||||||
// Create BMP file
|
// Create BMP file
|
||||||
FsFile coverBmp;
|
FsFile coverBmp;
|
||||||
if (!SdMan.openFileForWrite("XTC", getCoverBmpPath(), coverBmp)) {
|
if (!Storage.openFileForWrite("XTC", getCoverBmpPath(), coverBmp)) {
|
||||||
Serial.printf("[%lu] [XTC] Failed to create cover BMP file\n", millis());
|
Serial.printf("[%lu] [XTC] Failed to create cover BMP file\n", millis());
|
||||||
free(pageBuffer);
|
free(pageBuffer);
|
||||||
return false;
|
return false;
|
||||||
@@ -306,7 +306,7 @@ std::string Xtc::getThumbBmpPath(int height) const { return cachePath + "/thumb_
|
|||||||
|
|
||||||
bool Xtc::generateThumbBmp(int height) const {
|
bool Xtc::generateThumbBmp(int height) const {
|
||||||
// Already generated
|
// Already generated
|
||||||
if (SdMan.exists(getThumbBmpPath(height).c_str())) {
|
if (Storage.exists(getThumbBmpPath(height).c_str())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,8 +348,8 @@ bool Xtc::generateThumbBmp(int height) const {
|
|||||||
// Copy cover.bmp to thumb.bmp
|
// Copy cover.bmp to thumb.bmp
|
||||||
if (generateCoverBmp()) {
|
if (generateCoverBmp()) {
|
||||||
FsFile src, dst;
|
FsFile src, dst;
|
||||||
if (SdMan.openFileForRead("XTC", getCoverBmpPath(), src)) {
|
if (Storage.openFileForRead("XTC", getCoverBmpPath(), src)) {
|
||||||
if (SdMan.openFileForWrite("XTC", getThumbBmpPath(height), dst)) {
|
if (Storage.openFileForWrite("XTC", getThumbBmpPath(height), dst)) {
|
||||||
uint8_t buffer[512];
|
uint8_t buffer[512];
|
||||||
while (src.available()) {
|
while (src.available()) {
|
||||||
size_t bytesRead = src.read(buffer, sizeof(buffer));
|
size_t bytesRead = src.read(buffer, sizeof(buffer));
|
||||||
@@ -360,7 +360,7 @@ bool Xtc::generateThumbBmp(int height) const {
|
|||||||
src.close();
|
src.close();
|
||||||
}
|
}
|
||||||
Serial.printf("[%lu] [XTC] Copied cover to thumb (no scaling needed)\n", millis());
|
Serial.printf("[%lu] [XTC] Copied cover to thumb (no scaling needed)\n", millis());
|
||||||
return SdMan.exists(getThumbBmpPath(height).c_str());
|
return Storage.exists(getThumbBmpPath(height).c_str());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -394,7 +394,7 @@ bool Xtc::generateThumbBmp(int height) const {
|
|||||||
|
|
||||||
// Create thumbnail BMP file - use 1-bit format for fast home screen rendering (no gray passes)
|
// Create thumbnail BMP file - use 1-bit format for fast home screen rendering (no gray passes)
|
||||||
FsFile thumbBmp;
|
FsFile thumbBmp;
|
||||||
if (!SdMan.openFileForWrite("XTC", getThumbBmpPath(height), thumbBmp)) {
|
if (!Storage.openFileForWrite("XTC", getThumbBmpPath(height), thumbBmp)) {
|
||||||
Serial.printf("[%lu] [XTC] Failed to create thumb BMP file\n", millis());
|
Serial.printf("[%lu] [XTC] Failed to create thumb BMP file\n", millis());
|
||||||
free(pageBuffer);
|
free(pageBuffer);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
#include "XtcParser.h"
|
#include "XtcParser.h"
|
||||||
|
|
||||||
#include <FsHelpers.h>
|
#include <FsHelpers.h>
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ XtcError XtcParser::open(const char* filepath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
if (!SdMan.openFileForRead("XTC", filepath, m_file)) {
|
if (!Storage.openFileForRead("XTC", filepath, m_file)) {
|
||||||
m_lastError = XtcError::FILE_NOT_FOUND;
|
m_lastError = XtcError::FILE_NOT_FOUND;
|
||||||
return m_lastError;
|
return m_lastError;
|
||||||
}
|
}
|
||||||
@@ -444,7 +444,7 @@ XtcError XtcParser::loadPageStreaming(uint32_t pageIndex,
|
|||||||
|
|
||||||
bool XtcParser::isValidXtcFile(const char* filepath) {
|
bool XtcParser::isValidXtcFile(const char* filepath) {
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForRead("XTC", filepath, file)) {
|
if (!Storage.openFileForRead("XTC", filepath, file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SdFat.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "ZipFile.h"
|
#include "ZipFile.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
#include <miniz.h>
|
#include <miniz.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -279,7 +279,7 @@ bool ZipFile::loadZipDetails() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ZipFile::open() {
|
bool ZipFile::open() {
|
||||||
if (!SdMan.openFileForRead("ZIP", filePath, file)) {
|
if (!Storage.openFileForRead("ZIP", filePath, file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SdFat.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|||||||
65
lib/hal/HalStorage.cpp
Normal file
65
lib/hal/HalStorage.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include "HalStorage.h"
|
||||||
|
|
||||||
|
#include <SDCardManager.h>
|
||||||
|
|
||||||
|
#define SDCard SDCardManager::getInstance()
|
||||||
|
|
||||||
|
HalStorage HalStorage::instance;
|
||||||
|
|
||||||
|
HalStorage::HalStorage() {}
|
||||||
|
|
||||||
|
bool HalStorage::begin() { return SDCard.begin(); }
|
||||||
|
|
||||||
|
bool HalStorage::ready() const { return SDCard.ready(); }
|
||||||
|
|
||||||
|
std::vector<String> HalStorage::listFiles(const char* path, int maxFiles) { return SDCard.listFiles(path, maxFiles); }
|
||||||
|
|
||||||
|
String HalStorage::readFile(const char* path) { return SDCard.readFile(path); }
|
||||||
|
|
||||||
|
bool HalStorage::readFileToStream(const char* path, Print& out, size_t chunkSize) {
|
||||||
|
return SDCard.readFileToStream(path, out, chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HalStorage::readFileToBuffer(const char* path, char* buffer, size_t bufferSize, size_t maxBytes) {
|
||||||
|
return SDCard.readFileToBuffer(path, buffer, bufferSize, maxBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HalStorage::writeFile(const char* path, const String& content) { return SDCard.writeFile(path, content); }
|
||||||
|
|
||||||
|
bool HalStorage::ensureDirectoryExists(const char* path) { return SDCard.ensureDirectoryExists(path); }
|
||||||
|
|
||||||
|
FsFile HalStorage::open(const char* path, const oflag_t oflag) { return SDCard.open(path, oflag); }
|
||||||
|
|
||||||
|
bool HalStorage::mkdir(const char* path, const bool pFlag) { return SDCard.mkdir(path, pFlag); }
|
||||||
|
|
||||||
|
bool HalStorage::exists(const char* path) { return SDCard.exists(path); }
|
||||||
|
|
||||||
|
bool HalStorage::remove(const char* path) { return SDCard.remove(path); }
|
||||||
|
|
||||||
|
bool HalStorage::rmdir(const char* path) { return SDCard.rmdir(path); }
|
||||||
|
|
||||||
|
bool HalStorage::openFileForRead(const char* moduleName, const char* path, FsFile& file) {
|
||||||
|
return SDCard.openFileForRead(moduleName, path, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HalStorage::openFileForRead(const char* moduleName, const std::string& path, FsFile& file) {
|
||||||
|
return openFileForRead(moduleName, path.c_str(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HalStorage::openFileForRead(const char* moduleName, const String& path, FsFile& file) {
|
||||||
|
return openFileForRead(moduleName, path.c_str(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HalStorage::openFileForWrite(const char* moduleName, const char* path, FsFile& file) {
|
||||||
|
return SDCard.openFileForWrite(moduleName, path, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HalStorage::openFileForWrite(const char* moduleName, const std::string& path, FsFile& file) {
|
||||||
|
return openFileForWrite(moduleName, path.c_str(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HalStorage::openFileForWrite(const char* moduleName, const String& path, FsFile& file) {
|
||||||
|
return openFileForWrite(moduleName, path.c_str(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HalStorage::removeDir(const char* path) { return SDCard.removeDir(path); }
|
||||||
54
lib/hal/HalStorage.h
Normal file
54
lib/hal/HalStorage.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDCardManager.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class HalStorage {
|
||||||
|
public:
|
||||||
|
HalStorage();
|
||||||
|
bool begin();
|
||||||
|
bool ready() const;
|
||||||
|
std::vector<String> listFiles(const char* path = "/", int maxFiles = 200);
|
||||||
|
// Read the entire file at `path` into a String. Returns empty string on failure.
|
||||||
|
String readFile(const char* path);
|
||||||
|
// Low-memory helpers:
|
||||||
|
// Stream the file contents to a `Print` (e.g. `Serial`, or any `Print`-derived object).
|
||||||
|
// Returns true on success, false on failure.
|
||||||
|
bool readFileToStream(const char* path, Print& out, size_t chunkSize = 256);
|
||||||
|
// Read up to `bufferSize-1` bytes into `buffer`, null-terminating it. Returns bytes read.
|
||||||
|
size_t readFileToBuffer(const char* path, char* buffer, size_t bufferSize, size_t maxBytes = 0);
|
||||||
|
// Write a string to `path` on the SD card. Overwrites existing file.
|
||||||
|
// Returns true on success.
|
||||||
|
bool writeFile(const char* path, const String& content);
|
||||||
|
// Ensure a directory exists, creating it if necessary. Returns true on success.
|
||||||
|
bool ensureDirectoryExists(const char* path);
|
||||||
|
|
||||||
|
FsFile open(const char* path, const oflag_t oflag = O_RDONLY);
|
||||||
|
bool mkdir(const char* path, const bool pFlag = true);
|
||||||
|
bool exists(const char* path);
|
||||||
|
bool remove(const char* path);
|
||||||
|
bool rmdir(const char* path);
|
||||||
|
|
||||||
|
bool openFileForRead(const char* moduleName, const char* path, FsFile& file);
|
||||||
|
bool openFileForRead(const char* moduleName, const std::string& path, FsFile& file);
|
||||||
|
bool openFileForRead(const char* moduleName, const String& path, FsFile& file);
|
||||||
|
bool openFileForWrite(const char* moduleName, const char* path, FsFile& file);
|
||||||
|
bool openFileForWrite(const char* moduleName, const std::string& path, FsFile& file);
|
||||||
|
bool openFileForWrite(const char* moduleName, const String& path, FsFile& file);
|
||||||
|
bool removeDir(const char* path);
|
||||||
|
|
||||||
|
static HalStorage& getInstance() { return instance; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static HalStorage instance;
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define Storage HalStorage::getInstance()
|
||||||
|
|
||||||
|
// Downstream code must use Storage instead of SdMan
|
||||||
|
#ifdef SdMan
|
||||||
|
#undef SdMan
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
#include <Serialization.h>
|
#include <Serialization.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -79,10 +79,10 @@ void applyLegacyFrontButtonLayout(CrossPointSettings& settings) {
|
|||||||
|
|
||||||
bool CrossPointSettings::saveToFile() const {
|
bool CrossPointSettings::saveToFile() const {
|
||||||
// Make sure the directory exists
|
// Make sure the directory exists
|
||||||
SdMan.mkdir("/.crosspoint");
|
Storage.mkdir("/.crosspoint");
|
||||||
|
|
||||||
FsFile outputFile;
|
FsFile outputFile;
|
||||||
if (!SdMan.openFileForWrite("CPS", SETTINGS_FILE, outputFile)) {
|
if (!Storage.openFileForWrite("CPS", SETTINGS_FILE, outputFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ bool CrossPointSettings::saveToFile() const {
|
|||||||
|
|
||||||
bool CrossPointSettings::loadFromFile() {
|
bool CrossPointSettings::loadFromFile() {
|
||||||
FsFile inputFile;
|
FsFile inputFile;
|
||||||
if (!SdMan.openFileForRead("CPS", SETTINGS_FILE, inputFile)) {
|
if (!Storage.openFileForRead("CPS", SETTINGS_FILE, inputFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "CrossPointState.h"
|
#include "CrossPointState.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
#include <Serialization.h>
|
#include <Serialization.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -13,7 +13,7 @@ CrossPointState CrossPointState::instance;
|
|||||||
|
|
||||||
bool CrossPointState::saveToFile() const {
|
bool CrossPointState::saveToFile() const {
|
||||||
FsFile outputFile;
|
FsFile outputFile;
|
||||||
if (!SdMan.openFileForWrite("CPS", STATE_FILE, outputFile)) {
|
if (!Storage.openFileForWrite("CPS", STATE_FILE, outputFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ bool CrossPointState::saveToFile() const {
|
|||||||
|
|
||||||
bool CrossPointState::loadFromFile() {
|
bool CrossPointState::loadFromFile() {
|
||||||
FsFile inputFile;
|
FsFile inputFile;
|
||||||
if (!SdMan.openFileForRead("CPS", STATE_FILE, inputFile)) {
|
if (!Storage.openFileForRead("CPS", STATE_FILE, inputFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "RecentBooksStore.h"
|
#include "RecentBooksStore.h"
|
||||||
|
|
||||||
#include <Epub.h>
|
#include <Epub.h>
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
#include <Serialization.h>
|
#include <Serialization.h>
|
||||||
#include <Xtc.h>
|
#include <Xtc.h>
|
||||||
|
|
||||||
@@ -53,10 +53,10 @@ void RecentBooksStore::updateBook(const std::string& path, const std::string& ti
|
|||||||
|
|
||||||
bool RecentBooksStore::saveToFile() const {
|
bool RecentBooksStore::saveToFile() const {
|
||||||
// Make sure the directory exists
|
// Make sure the directory exists
|
||||||
SdMan.mkdir("/.crosspoint");
|
Storage.mkdir("/.crosspoint");
|
||||||
|
|
||||||
FsFile outputFile;
|
FsFile outputFile;
|
||||||
if (!SdMan.openFileForWrite("RBS", RECENT_BOOKS_FILE, outputFile)) {
|
if (!Storage.openFileForWrite("RBS", RECENT_BOOKS_FILE, outputFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ RecentBook RecentBooksStore::getDataFromBook(std::string path) const {
|
|||||||
|
|
||||||
bool RecentBooksStore::loadFromFile() {
|
bool RecentBooksStore::loadFromFile() {
|
||||||
FsFile inputFile;
|
FsFile inputFile;
|
||||||
if (!SdMan.openFileForRead("RBS", RECENT_BOOKS_FILE, inputFile)) {
|
if (!Storage.openFileForRead("RBS", RECENT_BOOKS_FILE, inputFile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "WifiCredentialStore.h"
|
#include "WifiCredentialStore.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
#include <Serialization.h>
|
#include <Serialization.h>
|
||||||
|
|
||||||
// Initialize the static instance
|
// Initialize the static instance
|
||||||
@@ -29,10 +29,10 @@ void WifiCredentialStore::obfuscate(std::string& data) const {
|
|||||||
|
|
||||||
bool WifiCredentialStore::saveToFile() const {
|
bool WifiCredentialStore::saveToFile() const {
|
||||||
// Make sure the directory exists
|
// Make sure the directory exists
|
||||||
SdMan.mkdir("/.crosspoint");
|
Storage.mkdir("/.crosspoint");
|
||||||
|
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForWrite("WCS", WIFI_FILE, file)) {
|
if (!Storage.openFileForWrite("WCS", WIFI_FILE, file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ bool WifiCredentialStore::saveToFile() const {
|
|||||||
|
|
||||||
bool WifiCredentialStore::loadFromFile() {
|
bool WifiCredentialStore::loadFromFile() {
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForRead("WCS", WIFI_FILE, file)) {
|
if (!Storage.openFileForRead("WCS", WIFI_FILE, file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <Epub.h>
|
#include <Epub.h>
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
#include <Txt.h>
|
#include <Txt.h>
|
||||||
#include <Xtc.h>
|
#include <Xtc.h>
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ void SleepActivity::onEnter() {
|
|||||||
|
|
||||||
void SleepActivity::renderCustomSleepScreen() const {
|
void SleepActivity::renderCustomSleepScreen() const {
|
||||||
// Check if we have a /sleep directory
|
// Check if we have a /sleep directory
|
||||||
auto dir = SdMan.open("/sleep");
|
auto dir = Storage.open("/sleep");
|
||||||
if (dir && dir.isDirectory()) {
|
if (dir && dir.isDirectory()) {
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
char name[500];
|
char name[500];
|
||||||
@@ -75,7 +75,7 @@ void SleepActivity::renderCustomSleepScreen() const {
|
|||||||
APP_STATE.saveToFile();
|
APP_STATE.saveToFile();
|
||||||
const auto filename = "/sleep/" + files[randomFileIndex];
|
const auto filename = "/sleep/" + files[randomFileIndex];
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (SdMan.openFileForRead("SLP", filename, file)) {
|
if (Storage.openFileForRead("SLP", filename, file)) {
|
||||||
Serial.printf("[%lu] [SLP] Randomly loading: /sleep/%s\n", millis(), files[randomFileIndex].c_str());
|
Serial.printf("[%lu] [SLP] Randomly loading: /sleep/%s\n", millis(), files[randomFileIndex].c_str());
|
||||||
delay(100);
|
delay(100);
|
||||||
Bitmap bitmap(file, true);
|
Bitmap bitmap(file, true);
|
||||||
@@ -92,7 +92,7 @@ void SleepActivity::renderCustomSleepScreen() const {
|
|||||||
// Look for sleep.bmp on the root of the sd card to determine if we should
|
// Look for sleep.bmp on the root of the sd card to determine if we should
|
||||||
// render a custom sleep screen instead of the default.
|
// render a custom sleep screen instead of the default.
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (SdMan.openFileForRead("SLP", "/sleep.bmp", file)) {
|
if (Storage.openFileForRead("SLP", "/sleep.bmp", file)) {
|
||||||
Bitmap bitmap(file, true);
|
Bitmap bitmap(file, true);
|
||||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||||
Serial.printf("[%lu] [SLP] Loading: /sleep.bmp\n", millis());
|
Serial.printf("[%lu] [SLP] Loading: /sleep.bmp\n", millis());
|
||||||
@@ -262,7 +262,7 @@ void SleepActivity::renderCoverSleepScreen() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (SdMan.openFileForRead("SLP", coverBmpPath, file)) {
|
if (Storage.openFileForRead("SLP", coverBmpPath, file)) {
|
||||||
Bitmap bitmap(file);
|
Bitmap bitmap(file);
|
||||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||||
Serial.printf("[SLP] Rendering sleep cover: %s\n", coverBmpPath.c_str());
|
Serial.printf("[SLP] Rendering sleep cover: %s\n", coverBmpPath.c_str());
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <Epub.h>
|
#include <Epub.h>
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
#include <Utf8.h>
|
#include <Utf8.h>
|
||||||
#include <Xtc.h>
|
#include <Xtc.h>
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ void HomeActivity::loadRecentBooks(int maxBooks) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip if file no longer exists
|
// Skip if file no longer exists
|
||||||
if (!SdMan.exists(book.path.c_str())) {
|
if (!Storage.exists(book.path.c_str())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ void HomeActivity::loadRecentCovers(int coverHeight) {
|
|||||||
for (RecentBook& book : recentBooks) {
|
for (RecentBook& book : recentBooks) {
|
||||||
if (!book.coverBmpPath.empty()) {
|
if (!book.coverBmpPath.empty()) {
|
||||||
std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight);
|
std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight);
|
||||||
if (!SdMan.exists(coverPath.c_str())) {
|
if (!Storage.exists(coverPath.c_str())) {
|
||||||
// If epub, try to load the metadata for title/author and cover
|
// If epub, try to load the metadata for title/author and cover
|
||||||
if (StringUtils::checkFileExtension(book.path, ".epub")) {
|
if (StringUtils::checkFileExtension(book.path, ".epub")) {
|
||||||
Epub epub(book.path, "/.crosspoint");
|
Epub epub(book.path, "/.crosspoint");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "MyLibraryActivity.h"
|
#include "MyLibraryActivity.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ void MyLibraryActivity::taskTrampoline(void* param) {
|
|||||||
void MyLibraryActivity::loadFiles() {
|
void MyLibraryActivity::loadFiles() {
|
||||||
files.clear();
|
files.clear();
|
||||||
|
|
||||||
auto root = SdMan.open(basepath.c_str());
|
auto root = Storage.open(basepath.c_str());
|
||||||
if (!root || !root.isDirectory()) {
|
if (!root || !root.isDirectory()) {
|
||||||
if (root) root.close();
|
if (root) root.close();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "RecentBooksActivity.h"
|
#include "RecentBooksActivity.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ void RecentBooksActivity::loadRecentBooks() {
|
|||||||
|
|
||||||
for (const auto& book : books) {
|
for (const auto& book : books) {
|
||||||
// Skip if file no longer exists
|
// Skip if file no longer exists
|
||||||
if (!SdMan.exists(book.path.c_str())) {
|
if (!Storage.exists(book.path.c_str())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
recentBooks.push_back(book);
|
recentBooks.push_back(book);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <Epub/Page.h>
|
#include <Epub/Page.h>
|
||||||
#include <FsHelpers.h>
|
#include <FsHelpers.h>
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "CrossPointState.h"
|
#include "CrossPointState.h"
|
||||||
@@ -77,7 +77,7 @@ void EpubReaderActivity::onEnter() {
|
|||||||
epub->setupCacheDir();
|
epub->setupCacheDir();
|
||||||
|
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (SdMan.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) {
|
if (Storage.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) {
|
||||||
uint8_t data[6];
|
uint8_t data[6];
|
||||||
int dataSize = f.read(data, 6);
|
int dataSize = f.read(data, 6);
|
||||||
if (dataSize == 4 || dataSize == 6) {
|
if (dataSize == 4 || dataSize == 6) {
|
||||||
@@ -654,7 +654,7 @@ void EpubReaderActivity::renderScreen() {
|
|||||||
|
|
||||||
void EpubReaderActivity::saveProgress(int spineIndex, int currentPage, int pageCount) {
|
void EpubReaderActivity::saveProgress(int spineIndex, int currentPage, int pageCount) {
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (SdMan.openFileForWrite("ERS", epub->getCachePath() + "/progress.bin", f)) {
|
if (Storage.openFileForWrite("ERS", epub->getCachePath() + "/progress.bin", f)) {
|
||||||
uint8_t data[6];
|
uint8_t data[6];
|
||||||
data[0] = currentSpineIndex & 0xFF;
|
data[0] = currentSpineIndex & 0xFF;
|
||||||
data[1] = (currentSpineIndex >> 8) & 0xFF;
|
data[1] = (currentSpineIndex >> 8) & 0xFF;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "ReaderActivity.h"
|
#include "ReaderActivity.h"
|
||||||
|
|
||||||
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include "Epub.h"
|
#include "Epub.h"
|
||||||
#include "EpubReaderActivity.h"
|
#include "EpubReaderActivity.h"
|
||||||
#include "Txt.h"
|
#include "Txt.h"
|
||||||
@@ -27,7 +29,7 @@ bool ReaderActivity::isTxtFile(const std::string& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
|
std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
|
||||||
if (!SdMan.exists(path.c_str())) {
|
if (!Storage.exists(path.c_str())) {
|
||||||
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -42,7 +44,7 @@ std::unique_ptr<Epub> ReaderActivity::loadEpub(const std::string& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Xtc> ReaderActivity::loadXtc(const std::string& path) {
|
std::unique_ptr<Xtc> ReaderActivity::loadXtc(const std::string& path) {
|
||||||
if (!SdMan.exists(path.c_str())) {
|
if (!Storage.exists(path.c_str())) {
|
||||||
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -57,7 +59,7 @@ std::unique_ptr<Xtc> ReaderActivity::loadXtc(const std::string& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Txt> ReaderActivity::loadTxt(const std::string& path) {
|
std::unique_ptr<Txt> ReaderActivity::loadTxt(const std::string& path) {
|
||||||
if (!SdMan.exists(path.c_str())) {
|
if (!Storage.exists(path.c_str())) {
|
||||||
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
Serial.printf("[%lu] [ ] File does not exist: %s\n", millis(), path.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "TxtReaderActivity.h"
|
#include "TxtReaderActivity.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
#include <Serialization.h>
|
#include <Serialization.h>
|
||||||
#include <Utf8.h>
|
#include <Utf8.h>
|
||||||
|
|
||||||
@@ -565,7 +565,7 @@ void TxtReaderActivity::renderStatusBar(const int orientedMarginRight, const int
|
|||||||
|
|
||||||
void TxtReaderActivity::saveProgress() const {
|
void TxtReaderActivity::saveProgress() const {
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (SdMan.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) {
|
if (Storage.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) {
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
data[0] = currentPage & 0xFF;
|
data[0] = currentPage & 0xFF;
|
||||||
data[1] = (currentPage >> 8) & 0xFF;
|
data[1] = (currentPage >> 8) & 0xFF;
|
||||||
@@ -578,7 +578,7 @@ void TxtReaderActivity::saveProgress() const {
|
|||||||
|
|
||||||
void TxtReaderActivity::loadProgress() {
|
void TxtReaderActivity::loadProgress() {
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (SdMan.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) {
|
if (Storage.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) {
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
if (f.read(data, 4) == 4) {
|
if (f.read(data, 4) == 4) {
|
||||||
currentPage = data[0] + (data[1] << 8);
|
currentPage = data[0] + (data[1] << 8);
|
||||||
@@ -609,7 +609,7 @@ bool TxtReaderActivity::loadPageIndexCache() {
|
|||||||
|
|
||||||
std::string cachePath = txt->getCachePath() + "/index.bin";
|
std::string cachePath = txt->getCachePath() + "/index.bin";
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (!SdMan.openFileForRead("TRS", cachePath, f)) {
|
if (!Storage.openFileForRead("TRS", cachePath, f)) {
|
||||||
Serial.printf("[%lu] [TRS] No page index cache found\n", millis());
|
Serial.printf("[%lu] [TRS] No page index cache found\n", millis());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -701,7 +701,7 @@ bool TxtReaderActivity::loadPageIndexCache() {
|
|||||||
void TxtReaderActivity::savePageIndexCache() const {
|
void TxtReaderActivity::savePageIndexCache() const {
|
||||||
std::string cachePath = txt->getCachePath() + "/index.bin";
|
std::string cachePath = txt->getCachePath() + "/index.bin";
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (!SdMan.openFileForWrite("TRS", cachePath, f)) {
|
if (!Storage.openFileForWrite("TRS", cachePath, f)) {
|
||||||
Serial.printf("[%lu] [TRS] Failed to save page index cache\n", millis());
|
Serial.printf("[%lu] [TRS] Failed to save page index cache\n", millis());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include <FsHelpers.h>
|
#include <FsHelpers.h>
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include "CrossPointSettings.h"
|
#include "CrossPointSettings.h"
|
||||||
#include "CrossPointState.h"
|
#include "CrossPointState.h"
|
||||||
@@ -372,7 +372,7 @@ void XtcReaderActivity::renderPage() {
|
|||||||
|
|
||||||
void XtcReaderActivity::saveProgress() const {
|
void XtcReaderActivity::saveProgress() const {
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (SdMan.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) {
|
if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) {
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
data[0] = currentPage & 0xFF;
|
data[0] = currentPage & 0xFF;
|
||||||
data[1] = (currentPage >> 8) & 0xFF;
|
data[1] = (currentPage >> 8) & 0xFF;
|
||||||
@@ -385,7 +385,7 @@ void XtcReaderActivity::saveProgress() const {
|
|||||||
|
|
||||||
void XtcReaderActivity::loadProgress() {
|
void XtcReaderActivity::loadProgress() {
|
||||||
FsFile f;
|
FsFile f;
|
||||||
if (SdMan.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) {
|
if (Storage.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) {
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
if (f.read(data, 4) == 4) {
|
if (f.read(data, 4) == 4) {
|
||||||
currentPage = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
currentPage = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "ClearCacheActivity.h"
|
#include "ClearCacheActivity.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
|
#include <HalStorage.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include <SDCardManager.h>
|
|
||||||
|
|
||||||
#include "MappedInputManager.h"
|
#include "MappedInputManager.h"
|
||||||
#include "components/UITheme.h"
|
#include "components/UITheme.h"
|
||||||
@@ -107,7 +107,7 @@ void ClearCacheActivity::clearCache() {
|
|||||||
Serial.printf("[%lu] [CLEAR_CACHE] Clearing cache...\n", millis());
|
Serial.printf("[%lu] [CLEAR_CACHE] Clearing cache...\n", millis());
|
||||||
|
|
||||||
// Open .crosspoint directory
|
// Open .crosspoint directory
|
||||||
auto root = SdMan.open("/.crosspoint");
|
auto root = Storage.open("/.crosspoint");
|
||||||
if (!root || !root.isDirectory()) {
|
if (!root || !root.isDirectory()) {
|
||||||
Serial.printf("[%lu] [CLEAR_CACHE] Failed to open cache directory\n", millis());
|
Serial.printf("[%lu] [CLEAR_CACHE] Failed to open cache directory\n", millis());
|
||||||
if (root) root.close();
|
if (root) root.close();
|
||||||
@@ -132,7 +132,7 @@ void ClearCacheActivity::clearCache() {
|
|||||||
|
|
||||||
file.close(); // Close before attempting to delete
|
file.close(); // Close before attempting to delete
|
||||||
|
|
||||||
if (SdMan.removeDir(fullPath.c_str())) {
|
if (Storage.removeDir(fullPath.c_str())) {
|
||||||
clearedCount++;
|
clearedCount++;
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("[%lu] [CLEAR_CACHE] Failed to remove: %s\n", millis(), fullPath.c_str());
|
Serial.printf("[%lu] [CLEAR_CACHE] Failed to remove: %s\n", millis(), fullPath.c_str());
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "BaseTheme.h"
|
#include "BaseTheme.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
#include <Utf8.h>
|
#include <Utf8.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -308,7 +308,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
|
|||||||
|
|
||||||
// First time: load cover from SD and render
|
// First time: load cover from SD and render
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (SdMan.openFileForRead("HOME", coverBmpPath, file)) {
|
if (Storage.openFileForRead("HOME", coverBmpPath, file)) {
|
||||||
Bitmap bitmap(file);
|
Bitmap bitmap(file);
|
||||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||||
Serial.printf("Rendering bmp\n");
|
Serial.printf("Rendering bmp\n");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "LyraTheme.h"
|
#include "LyraTheme.h"
|
||||||
|
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -283,7 +283,7 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
|
|||||||
|
|
||||||
// First time: load cover from SD and render
|
// First time: load cover from SD and render
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (SdMan.openFileForRead("HOME", coverBmpPath, file)) {
|
if (Storage.openFileForRead("HOME", coverBmpPath, file)) {
|
||||||
Bitmap bitmap(file);
|
Bitmap bitmap(file);
|
||||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||||
float coverHeight = static_cast<float>(bitmap.getHeight());
|
float coverHeight = static_cast<float>(bitmap.getHeight());
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <HalDisplay.h>
|
#include <HalDisplay.h>
|
||||||
#include <HalGPIO.h>
|
#include <HalGPIO.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <builtinFonts/all.h>
|
#include <builtinFonts/all.h>
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ void setup() {
|
|||||||
|
|
||||||
// SD Card Initialization
|
// SD Card Initialization
|
||||||
// We need 6 open files concurrently when parsing a new chapter
|
// We need 6 open files concurrently when parsing a new chapter
|
||||||
if (!SdMan.begin()) {
|
if (!Storage.begin()) {
|
||||||
Serial.printf("[%lu] [ ] SD card initialization failed\n", millis());
|
Serial.printf("[%lu] [ ] SD card initialization failed\n", millis());
|
||||||
setupDisplayAndFonts();
|
setupDisplayAndFonts();
|
||||||
exitActivity();
|
exitActivity();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <Epub.h>
|
#include <Epub.h>
|
||||||
#include <FsHelpers.h>
|
#include <FsHelpers.h>
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <esp_task_wdt.h>
|
#include <esp_task_wdt.h>
|
||||||
|
|
||||||
@@ -316,7 +316,7 @@ void CrossPointWebServer::handleStatus() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CrossPointWebServer::scanFiles(const char* path, const std::function<void(FileInfo)>& callback) const {
|
void CrossPointWebServer::scanFiles(const char* path, const std::function<void(FileInfo)>& callback) const {
|
||||||
FsFile root = SdMan.open(path);
|
FsFile root = Storage.open(path);
|
||||||
if (!root) {
|
if (!root) {
|
||||||
Serial.printf("[%lu] [WEB] Failed to open directory: %s\n", millis(), path);
|
Serial.printf("[%lu] [WEB] Failed to open directory: %s\n", millis(), path);
|
||||||
return;
|
return;
|
||||||
@@ -458,12 +458,12 @@ void CrossPointWebServer::handleDownload() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.exists(itemPath.c_str())) {
|
if (!Storage.exists(itemPath.c_str())) {
|
||||||
server->send(404, "text/plain", "Item not found");
|
server->send(404, "text/plain", "Item not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile file = SdMan.open(itemPath.c_str());
|
FsFile file = Storage.open(itemPath.c_str());
|
||||||
if (!file) {
|
if (!file) {
|
||||||
server->send(500, "text/plain", "Failed to open file");
|
server->send(500, "text/plain", "Failed to open file");
|
||||||
return;
|
return;
|
||||||
@@ -574,15 +574,15 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
|||||||
|
|
||||||
// Check if file already exists - SD operations can be slow
|
// Check if file already exists - SD operations can be slow
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
if (SdMan.exists(filePath.c_str())) {
|
if (Storage.exists(filePath.c_str())) {
|
||||||
Serial.printf("[%lu] [WEB] [UPLOAD] Overwriting existing file: %s\n", millis(), filePath.c_str());
|
Serial.printf("[%lu] [WEB] [UPLOAD] Overwriting existing file: %s\n", millis(), filePath.c_str());
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
SdMan.remove(filePath.c_str());
|
Storage.remove(filePath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open file for writing - this can be slow due to FAT cluster allocation
|
// Open file for writing - this can be slow due to FAT cluster allocation
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
if (!SdMan.openFileForWrite("WEB", filePath, state.file)) {
|
if (!Storage.openFileForWrite("WEB", filePath, state.file)) {
|
||||||
state.error = "Failed to create file on SD card";
|
state.error = "Failed to create file on SD card";
|
||||||
Serial.printf("[%lu] [WEB] [UPLOAD] FAILED to create file: %s\n", millis(), filePath.c_str());
|
Serial.printf("[%lu] [WEB] [UPLOAD] FAILED to create file: %s\n", millis(), filePath.c_str());
|
||||||
return;
|
return;
|
||||||
@@ -660,7 +660,7 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
|
|||||||
String filePath = state.path;
|
String filePath = state.path;
|
||||||
if (!filePath.endsWith("/")) filePath += "/";
|
if (!filePath.endsWith("/")) filePath += "/";
|
||||||
filePath += state.fileName;
|
filePath += state.fileName;
|
||||||
SdMan.remove(filePath.c_str());
|
Storage.remove(filePath.c_str());
|
||||||
}
|
}
|
||||||
state.error = "Upload aborted";
|
state.error = "Upload aborted";
|
||||||
Serial.printf("[%lu] [WEB] Upload aborted\n", millis());
|
Serial.printf("[%lu] [WEB] Upload aborted\n", millis());
|
||||||
@@ -711,13 +711,13 @@ void CrossPointWebServer::handleCreateFolder() const {
|
|||||||
Serial.printf("[%lu] [WEB] Creating folder: %s\n", millis(), folderPath.c_str());
|
Serial.printf("[%lu] [WEB] Creating folder: %s\n", millis(), folderPath.c_str());
|
||||||
|
|
||||||
// Check if already exists
|
// Check if already exists
|
||||||
if (SdMan.exists(folderPath.c_str())) {
|
if (Storage.exists(folderPath.c_str())) {
|
||||||
server->send(400, "text/plain", "Folder already exists");
|
server->send(400, "text/plain", "Folder already exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the folder
|
// Create the folder
|
||||||
if (SdMan.mkdir(folderPath.c_str())) {
|
if (Storage.mkdir(folderPath.c_str())) {
|
||||||
Serial.printf("[%lu] [WEB] Folder created successfully: %s\n", millis(), folderPath.c_str());
|
Serial.printf("[%lu] [WEB] Folder created successfully: %s\n", millis(), folderPath.c_str());
|
||||||
server->send(200, "text/plain", "Folder created: " + folderName);
|
server->send(200, "text/plain", "Folder created: " + folderName);
|
||||||
} else {
|
} else {
|
||||||
@@ -763,12 +763,12 @@ void CrossPointWebServer::handleRename() const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.exists(itemPath.c_str())) {
|
if (!Storage.exists(itemPath.c_str())) {
|
||||||
server->send(404, "text/plain", "Item not found");
|
server->send(404, "text/plain", "Item not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile file = SdMan.open(itemPath.c_str());
|
FsFile file = Storage.open(itemPath.c_str());
|
||||||
if (!file) {
|
if (!file) {
|
||||||
server->send(500, "text/plain", "Failed to open file");
|
server->send(500, "text/plain", "Failed to open file");
|
||||||
return;
|
return;
|
||||||
@@ -789,7 +789,7 @@ void CrossPointWebServer::handleRename() const {
|
|||||||
}
|
}
|
||||||
newPath += newName;
|
newPath += newName;
|
||||||
|
|
||||||
if (SdMan.exists(newPath.c_str())) {
|
if (Storage.exists(newPath.c_str())) {
|
||||||
file.close();
|
file.close();
|
||||||
server->send(409, "text/plain", "Target already exists");
|
server->send(409, "text/plain", "Target already exists");
|
||||||
return;
|
return;
|
||||||
@@ -839,12 +839,12 @@ void CrossPointWebServer::handleMove() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.exists(itemPath.c_str())) {
|
if (!Storage.exists(itemPath.c_str())) {
|
||||||
server->send(404, "text/plain", "Item not found");
|
server->send(404, "text/plain", "Item not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsFile file = SdMan.open(itemPath.c_str());
|
FsFile file = Storage.open(itemPath.c_str());
|
||||||
if (!file) {
|
if (!file) {
|
||||||
server->send(500, "text/plain", "Failed to open file");
|
server->send(500, "text/plain", "Failed to open file");
|
||||||
return;
|
return;
|
||||||
@@ -855,12 +855,12 @@ void CrossPointWebServer::handleMove() const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SdMan.exists(destPath.c_str())) {
|
if (!Storage.exists(destPath.c_str())) {
|
||||||
file.close();
|
file.close();
|
||||||
server->send(404, "text/plain", "Destination not found");
|
server->send(404, "text/plain", "Destination not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FsFile destDir = SdMan.open(destPath.c_str());
|
FsFile destDir = Storage.open(destPath.c_str());
|
||||||
if (!destDir || !destDir.isDirectory()) {
|
if (!destDir || !destDir.isDirectory()) {
|
||||||
if (destDir) {
|
if (destDir) {
|
||||||
destDir.close();
|
destDir.close();
|
||||||
@@ -882,7 +882,7 @@ void CrossPointWebServer::handleMove() const {
|
|||||||
server->send(200, "text/plain", "Already in destination");
|
server->send(200, "text/plain", "Already in destination");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (SdMan.exists(newPath.c_str())) {
|
if (Storage.exists(newPath.c_str())) {
|
||||||
file.close();
|
file.close();
|
||||||
server->send(409, "text/plain", "Target already exists");
|
server->send(409, "text/plain", "Target already exists");
|
||||||
return;
|
return;
|
||||||
@@ -942,7 +942,7 @@ void CrossPointWebServer::handleDelete() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if item exists
|
// Check if item exists
|
||||||
if (!SdMan.exists(itemPath.c_str())) {
|
if (!Storage.exists(itemPath.c_str())) {
|
||||||
Serial.printf("[%lu] [WEB] Delete failed - item not found: %s\n", millis(), itemPath.c_str());
|
Serial.printf("[%lu] [WEB] Delete failed - item not found: %s\n", millis(), itemPath.c_str());
|
||||||
server->send(404, "text/plain", "Item not found");
|
server->send(404, "text/plain", "Item not found");
|
||||||
return;
|
return;
|
||||||
@@ -954,7 +954,7 @@ void CrossPointWebServer::handleDelete() const {
|
|||||||
|
|
||||||
if (itemType == "folder") {
|
if (itemType == "folder") {
|
||||||
// For folders, try to remove (will fail if not empty)
|
// For folders, try to remove (will fail if not empty)
|
||||||
FsFile dir = SdMan.open(itemPath.c_str());
|
FsFile dir = Storage.open(itemPath.c_str());
|
||||||
if (dir && dir.isDirectory()) {
|
if (dir && dir.isDirectory()) {
|
||||||
// Check if folder is empty
|
// Check if folder is empty
|
||||||
FsFile entry = dir.openNextFile();
|
FsFile entry = dir.openNextFile();
|
||||||
@@ -968,10 +968,10 @@ void CrossPointWebServer::handleDelete() const {
|
|||||||
}
|
}
|
||||||
dir.close();
|
dir.close();
|
||||||
}
|
}
|
||||||
success = SdMan.rmdir(itemPath.c_str());
|
success = Storage.rmdir(itemPath.c_str());
|
||||||
} else {
|
} else {
|
||||||
// For files, use remove
|
// For files, use remove
|
||||||
success = SdMan.remove(itemPath.c_str());
|
success = Storage.remove(itemPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -1007,7 +1007,7 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
|
|||||||
String filePath = wsUploadPath;
|
String filePath = wsUploadPath;
|
||||||
if (!filePath.endsWith("/")) filePath += "/";
|
if (!filePath.endsWith("/")) filePath += "/";
|
||||||
filePath += wsUploadFileName;
|
filePath += wsUploadFileName;
|
||||||
SdMan.remove(filePath.c_str());
|
Storage.remove(filePath.c_str());
|
||||||
Serial.printf("[%lu] [WS] Deleted incomplete upload: %s\n", millis(), filePath.c_str());
|
Serial.printf("[%lu] [WS] Deleted incomplete upload: %s\n", millis(), filePath.c_str());
|
||||||
}
|
}
|
||||||
wsUploadInProgress = false;
|
wsUploadInProgress = false;
|
||||||
@@ -1051,13 +1051,13 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
|
|||||||
|
|
||||||
// Check if file exists and remove it
|
// Check if file exists and remove it
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
if (SdMan.exists(filePath.c_str())) {
|
if (Storage.exists(filePath.c_str())) {
|
||||||
SdMan.remove(filePath.c_str());
|
Storage.remove(filePath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open file for writing
|
// Open file for writing
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
if (!SdMan.openFileForWrite("WS", filePath, wsUploadFile)) {
|
if (!Storage.openFileForWrite("WS", filePath, wsUploadFile)) {
|
||||||
wsServer->sendTXT(num, "ERROR:Failed to create file");
|
wsServer->sendTXT(num, "ERROR:Failed to create file");
|
||||||
wsUploadInProgress = false;
|
wsUploadInProgress = false;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
#include <WebSocketsServer.h>
|
#include <WebSocketsServer.h>
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
|
|||||||
@@ -100,13 +100,13 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
|||||||
Serial.printf("[%lu] [HTTP] Content-Length: %zu\n", millis(), contentLength);
|
Serial.printf("[%lu] [HTTP] Content-Length: %zu\n", millis(), contentLength);
|
||||||
|
|
||||||
// Remove existing file if present
|
// Remove existing file if present
|
||||||
if (SdMan.exists(destPath.c_str())) {
|
if (Storage.exists(destPath.c_str())) {
|
||||||
SdMan.remove(destPath.c_str());
|
Storage.remove(destPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open file for writing
|
// Open file for writing
|
||||||
FsFile file;
|
FsFile file;
|
||||||
if (!SdMan.openFileForWrite("HTTP", destPath.c_str(), file)) {
|
if (!Storage.openFileForWrite("HTTP", destPath.c_str(), file)) {
|
||||||
Serial.printf("[%lu] [HTTP] Failed to open file for writing\n", millis());
|
Serial.printf("[%lu] [HTTP] Failed to open file for writing\n", millis());
|
||||||
http.end();
|
http.end();
|
||||||
return FILE_ERROR;
|
return FILE_ERROR;
|
||||||
@@ -117,7 +117,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
|||||||
if (!stream) {
|
if (!stream) {
|
||||||
Serial.printf("[%lu] [HTTP] Failed to get stream\n", millis());
|
Serial.printf("[%lu] [HTTP] Failed to get stream\n", millis());
|
||||||
file.close();
|
file.close();
|
||||||
SdMan.remove(destPath.c_str());
|
Storage.remove(destPath.c_str());
|
||||||
http.end();
|
http.end();
|
||||||
return HTTP_ERROR;
|
return HTTP_ERROR;
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
|||||||
if (written != bytesRead) {
|
if (written != bytesRead) {
|
||||||
Serial.printf("[%lu] [HTTP] Write failed: wrote %zu of %zu bytes\n", millis(), written, bytesRead);
|
Serial.printf("[%lu] [HTTP] Write failed: wrote %zu of %zu bytes\n", millis(), written, bytesRead);
|
||||||
file.close();
|
file.close();
|
||||||
SdMan.remove(destPath.c_str());
|
Storage.remove(destPath.c_str());
|
||||||
http.end();
|
http.end();
|
||||||
return FILE_ERROR;
|
return FILE_ERROR;
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
|
|||||||
// Verify download size if known
|
// Verify download size if known
|
||||||
if (contentLength > 0 && downloaded != contentLength) {
|
if (contentLength > 0 && downloaded != contentLength) {
|
||||||
Serial.printf("[%lu] [HTTP] Size mismatch: got %zu, expected %zu\n", millis(), downloaded, contentLength);
|
Serial.printf("[%lu] [HTTP] Size mismatch: got %zu, expected %zu\n", millis(), downloaded, contentLength);
|
||||||
SdMan.remove(destPath.c_str());
|
Storage.remove(destPath.c_str());
|
||||||
return HTTP_ERROR;
|
return HTTP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SDCardManager.h>
|
#include <HalStorage.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
Reference in New Issue
Block a user