2019-11-14 19:42:02 +00:00
|
|
|
#include "playlist_manager.h"
|
|
|
|
#include <SD.h>
|
|
|
|
#include "spi_master.h"
|
2019-11-16 22:03:13 +00:00
|
|
|
#include <ArduinoJson.h>
|
2019-11-14 19:42:02 +00:00
|
|
|
|
|
|
|
PlaylistManager::PlaylistManager() {
|
|
|
|
SPIMaster::select_sd();
|
|
|
|
File root = SD.open("/");
|
|
|
|
File entry;
|
|
|
|
while (entry = root.openNextFile()) {
|
|
|
|
String foldername = entry.name();
|
2019-11-16 22:03:13 +00:00
|
|
|
if (!entry.isDirectory() || foldername.startsWith("/.")) continue;
|
2019-11-14 19:42:02 +00:00
|
|
|
// Remove trailing slash
|
|
|
|
foldername.remove(foldername.length());
|
2019-11-16 22:03:13 +00:00
|
|
|
DEBUG(" Checking %s...\n", foldername.c_str());
|
|
|
|
bool non_ascii_chars = false;
|
|
|
|
for(int i=0; i<foldername.length(); i++) {
|
|
|
|
char c = foldername.charAt(i);
|
|
|
|
if (c < 0x20 || c >= 0x7F) {
|
|
|
|
non_ascii_chars = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (non_ascii_chars) {
|
|
|
|
ERROR("WARNING: Folder '%s' contains non-ascii chars!\n", foldername.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-11-14 19:42:02 +00:00
|
|
|
if (!SD.exists(foldername + "/ids.txt")) {
|
2019-11-16 22:03:13 +00:00
|
|
|
TRACE("No ids.txt -> checking for media files...\n");
|
|
|
|
|
|
|
|
File file;
|
|
|
|
bool media_files = false;
|
|
|
|
while(file = entry.openNextFile()) {
|
|
|
|
String filename = file.name();
|
|
|
|
filename = filename.substring(foldername.length() + 1);
|
|
|
|
if (!filename.startsWith(".") && filename.endsWith(".mp3")) {
|
|
|
|
media_files = true;
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
if (media_files) break;
|
|
|
|
}
|
|
|
|
if (media_files) {
|
|
|
|
_unmapped_folders.push_back(foldername);
|
|
|
|
}
|
2019-11-14 19:42:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
File f = SD.open(foldername + "/ids.txt");
|
|
|
|
String buffer = "";
|
|
|
|
if (f.available()) {
|
|
|
|
do {
|
|
|
|
char c = f.read();
|
|
|
|
if (!f.available() && c!='\n' && c!='\r') {
|
|
|
|
buffer.concat(c);
|
|
|
|
c='\n';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c=='\n' || c=='\r') {
|
|
|
|
if (buffer.length() > 0) {
|
|
|
|
_map[buffer] = foldername;
|
|
|
|
TRACE(" ID %s", buffer.c_str());
|
|
|
|
buffer="";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
buffer.concat(c);
|
|
|
|
}
|
|
|
|
} while(f.available());
|
|
|
|
}
|
|
|
|
f.close();
|
|
|
|
entry.close();
|
|
|
|
}
|
|
|
|
root.close();
|
|
|
|
SPIMaster::select_sd(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Playlist* PlaylistManager::get_playlist_for_id(String id) {
|
|
|
|
if (!_map.count(id)) return NULL;
|
|
|
|
String folder = _map[id];
|
2019-11-16 22:03:13 +00:00
|
|
|
return get_playlist_for_folder(folder);
|
|
|
|
}
|
|
|
|
|
|
|
|
Playlist* PlaylistManager::get_playlist_for_folder(String folder) {
|
2019-11-14 19:42:02 +00:00
|
|
|
if (!_playlists.count(folder)) {
|
|
|
|
_playlists[folder] = new Playlist(folder);
|
|
|
|
}
|
|
|
|
return _playlists[folder];
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlaylistManager::dump_ids() {
|
|
|
|
for (std::map<String, String>::iterator it = _map.begin(); it!=_map.end(); it++) {
|
|
|
|
INFO(" %s -> %s\n", it->first.c_str(), it->second.c_str());
|
|
|
|
}
|
|
|
|
}
|
2019-11-16 22:03:13 +00:00
|
|
|
|
|
|
|
String PlaylistManager::json() {
|
|
|
|
DynamicJsonDocument json(10240);
|
|
|
|
json["_type"] = "playlist_manager";
|
|
|
|
JsonObject folders = json.createNestedObject("folders");
|
|
|
|
for (std::map<String, String>::iterator it = _map.begin(); it!=_map.end(); it++) {
|
|
|
|
folders[it->second] = folders[it->first];
|
|
|
|
}
|
|
|
|
JsonArray started = json.createNestedArray("started");
|
|
|
|
for (std::map<String, Playlist*>::iterator it = _playlists.begin(); it!=_playlists.end(); it++) {
|
|
|
|
if (it->second->is_fresh()) continue;
|
|
|
|
started.add(it->first);
|
|
|
|
}
|
|
|
|
JsonArray unmapped = json.createNestedArray("unmapped");
|
|
|
|
for(String folder : _unmapped_folders) {
|
|
|
|
unmapped.add(folder);
|
|
|
|
}
|
|
|
|
return json.as<String>();
|
|
|
|
}
|