3 #include "AudioTools/CoreAudio/AudioBasic/Str.h"
5 #define MAX_FILE_LEN 256
18 template <
class SDT,
class FileT>
21 SDIndex(SDT &sd) { p_sd = &sd; };
22 void begin(
const char *startDir,
const char *extension,
23 const char *file_name_pattern,
bool setupIndex =
true) {
25 this->start_dir = startDir;
26 this->ext = extension;
27 this->file_name_pattern = file_name_pattern;
28 idx_path = filePathString(startDir,
"idx.txt");
29 idx_defpath = filePathString(startDir,
"idx-def.txt");
30 int idx_file_size = indexFileTSize();
31 LOGI(
"Index file size: %d", idx_file_size);
33 String(startDir) +
"|" + extension +
"|" + file_name_pattern;
34 String keyOld = getIndexDef();
35 if (setupIndex && (keyNew != keyOld || idx_file_size == 0)) {
36 FileT idxfile = p_sd->open(idx_path.c_str(), FILE_WRITE);
37 LOGW(
"Creating index file");
39 LOGI(
"Indexing completed");
46 void ls(
Print &p,
const char *startDir,
const char *extension,
47 const char *file_name_pattern =
"*") {
49 this->ext = extension;
50 this->file_name_pattern = file_name_pattern;
52 file_path_stack.clear();
53 file_path_str.clear();
59 if (max_idx >= 0 && idx > max_idx) {
60 LOGE(
"idx %d > size %d", idx, max_idx);
64 FileT idxfile = p_sd->open(idx_path.c_str());
67 if (idxfile.available() == 0) {
68 LOGE(
"Index file is empty");
72 while (idxfile.available() > 0 && !found) {
73 result = idxfile.readStringUntil(
'\n');
76 char *c_str = (
char *)result.c_str();
78 int lastPos = result.length() - 1;
79 if (c_str[lastPos] == 13) {
83 LOGD(
"%d -> %s", count, c_str);
94 return found ? result.c_str() :
nullptr;
99 FileT idxfile = p_sd->open(idx_path.c_str());
102 while (idxfile.available() > 0) {
103 result = idxfile.readStringUntil(
'\n');
105 char *c_str = (
char *)result.c_str();
119 List<String> file_path_stack;
120 String file_path_str;
121 const char *start_dir;
123 const char *ext =
nullptr;
124 const char *file_name_pattern =
nullptr;
127 String filePathString(
const char *name,
const char *suffix) {
128 String result = name;
129 return result.endsWith(
"/") ? result + suffix : result +
"/" + suffix;
134 LOGD(
"listDir: %s", dirname);
135 FileT root = open(dirname);
137 LOGE(
"Open failed: %s", dirname);
141 if (!isDirectory(root)) {
142 LOGD(
"Is not directory: %s", dirname);
146 if (
StrView(dirname).startsWith(
".")) {
147 LOGD(
"Invalid file: %s", dirname);
153 FileT file = openNext(root);
155 if (isDirectory(file)) {
157 LOGD(
"name: %s", name.c_str());
159 listDir(idxfile, name.c_str());
163 LOGD(
"Adding file to index: %s", fn);
166 LOGD(
"Ignoring %s", fn);
169 file = openNext(root);
174 bool isDirectory(FileT &f) {
179 result = f.isDirectory();
181 LOGD(
"isDirectory %s: %d",
fileName(f), result);
185 FileT openNext(FileT &dir) {
189 if (!result.openNext(&dir, O_READ)) {
190 LOGD(
"No next file");
194 return dir.openNextFile();
198 void pushPath(
const char *name) {
199 LOGD(
"pushPath: %s", name);
200 LOGD(
"pushPath: %s", name);
201 String nameStr(name);
202 file_path_stack.push_back(nameStr);
208 file_path_stack.pop_back(str);
209 LOGD(
"popPath: %s", str.c_str());
215 const char *file_name =
fileName(file);
216 if (file.isDirectory()) {
217 LOGD(
"-> isValidAudioFile: '%s': %d", file_name,
false);
220 StrView strFileTName(file_name);
222 strFileTName.
matches(file_name_pattern) && !isHidden(file);
223 LOGD(
"-> isValidAudioFile: '%s': %d", file_name, result);
227 String getIndexDef() {
228 FileT idxdef = p_sd->open(idx_defpath.c_str());
229 String key1 = idxdef.readString();
233 void saveIndexDef(String keyNew) {
234 FileT idxdef = p_sd->open(idx_defpath.c_str(), FILE_WRITE);
235 idxdef.write((
const uint8_t *)keyNew.c_str(), keyNew.length());
239 size_t indexFileTSize() {
240 FileT idxfile = p_sd->open(idx_path.c_str());
241 size_t result = idxfile.size();
246 void rewind(FileT &f) {
259 static char name[MAX_FILE_LEN];
260 file.getName(name, MAX_FILE_LEN);
269 return file.name() + pos;
275 #if defined(USE_SDFAT) || ESP_IDF_VERSION_MAJOR >= 4
276 LOGD(
"-> fileNamePath: %s",
fileName(file));
277 file_path_str = start_dir;
278 if (!file_path_str.endsWith(
"/")) {
279 file_path_str +=
"/";
281 for (
int j = 0; j < file_path_stack.size(); j++) {
282 file_path_str += file_path_stack[j] +
"/";
285 static char name[MAX_FILE_LEN];
286 strncpy(name,
fileName(file), MAX_FILE_LEN);
287 file_path_str += name;
288 const char *result = file_path_str.c_str();
289 LOGD(
"<- fileNamePath: %s", result);
296 bool isHidden(FileT &f) {
304 FileT open(
const char *name) {
308 if (!result.open(name)) {
309 LOGE(
"FileT open error: %s", name);
313 return p_sd->open(name);