Reload folder mappings after modifying a mapping.

This commit is contained in:
Fabian Schlenz 2019-11-17 14:26:23 +01:00
parent b5ec78ab41
commit e1dd004cf5
4 changed files with 106 additions and 64 deletions

View File

@ -57,4 +57,5 @@ public:
String json(); String json();
bool process_message(String m); bool process_message(String m);
void queue_command(String cmd); void queue_command(String cmd);
void update_playlist_manager();
}; };

View File

@ -9,11 +9,14 @@ private:
std::map<String, String> _map; std::map<String, String> _map;
std::map<String, Playlist*> _playlists; std::map<String, Playlist*> _playlists;
std::vector<String> _unmapped_folders; std::vector<String> _unmapped_folders;
void _check_for_special_chars(String s);
void _save_mapping();
public: public:
PlaylistManager(); PlaylistManager();
Playlist* get_playlist_for_id(String id); Playlist* get_playlist_for_id(String id);
Playlist* get_playlist_for_folder(String folder); Playlist* get_playlist_for_folder(String folder);
void dump_ids(); void dump_ids();
void scan_files();
String json(); String json();
bool add_mapping(String id, String folder); bool add_mapping(String id, String folder);
}; };

View File

@ -123,7 +123,8 @@ void Controller::_check_rfid() {
} }
} }
if (pl==NULL) { if (pl==NULL) {
INFO("Could not find album for id '%s'.", s_uid.c_str()); INFO("Could not find album for id '%s'.\n", s_uid.c_str());
send_controller_status();
return; return;
} }
int index; int index;
@ -412,5 +413,11 @@ void Controller::inform_new_client(AsyncWebSocketClient* client) {
} }
void Controller::queue_command(String s) { void Controller::queue_command(String s) {
DEBUG("Enqeueing command '%s'.\n", s.c_str());
_cmd_queue = s; _cmd_queue = s;
} }
void Controller::update_playlist_manager() {
_pm->scan_files();
send_playlist_manager_status();
}

View File

@ -4,75 +4,97 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
PlaylistManager::PlaylistManager() { PlaylistManager::PlaylistManager() {
scan_files();
}
void PlaylistManager::scan_files() {
SPIMaster::select_sd(); SPIMaster::select_sd();
std::vector<String> folders;
File root = SD.open("/"); File root = SD.open("/");
File entry; File entry;
while (entry = root.openNextFile()) { while (entry = root.openNextFile()) {
String foldername = entry.name(); String foldername = entry.name();
if (!entry.isDirectory() || foldername.startsWith("/.")) continue; if (foldername.startsWith("/.")) continue;
// Remove trailing slash
foldername.remove(foldername.length()); foldername.remove(foldername.length());
DEBUG(" Checking %s...\n", foldername.c_str()); folders.push_back(foldername);
bool non_ascii_chars = false; _check_for_special_chars(foldername);
for(int i=0; i<foldername.length(); i++) { entry.close();
char c = foldername.charAt(i); }
if (c < 0x20 || c >= 0x7F) {
non_ascii_chars = true; _map.clear();
if (!SD.exists("/_mapping.txt\n")) {
ERROR("WARNING: File /_mapping.txt not found.\n");
} else {
File f = SD.open("/_mapping.txt");
DEBUG("Reading /_mapping.txt...\n");
while (f.available()) {
char buffer[512];
size_t pos = f.readBytesUntil('\n', buffer, 511);
buffer[pos] = '\0';
String data = buffer;
uint8_t eq = data.indexOf('=');
if (eq>0 && eq<data.length()-1) {
String rfid_id = data.substring(0, eq);
String folder = data.substring(eq + 1);
TRACE(" Adding mapping: %s=>%s\n", rfid_id.c_str(), folder.c_str());
_map[rfid_id] = folder;
bool found=false;
for (String f: folders) {
if (f.equals(folder)) {
found = true;
break;
}
}
if (!found) {
INFO("WARNING: Found mapping for RFID id %s which maps to non-existing folder %s!\n", rfid_id.c_str(), folder.c_str());
}
}
}
f.close();
}
root.close();
_unmapped_folders.clear();
for (String folder: folders) {
bool found = false;
for(std::map<String, String>::iterator it = _map.begin(); it != _map.end(); it++) {
if (it->second.equals(folder)) {
found = true;
break; break;
} }
} }
if (non_ascii_chars) { if (!found) {
ERROR("WARNING: Folder '%s' contains non-ascii chars!\n", foldername.c_str()); // Checking folder for media files
} File dir = SD.open(folder);
while (entry = dir.openNextFile()) {
String filename = entry.name();
if (!SD.exists(foldername + "/ids.txt")) { filename = filename.substring(folder.length() + 1);
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")) { if (!filename.startsWith(".") && filename.endsWith(".mp3")) {
media_files = true; found = true;
} }
file.close(); entry.close();
if (media_files) break; if (found) break;
} }
if (media_files) { if (found) {
_unmapped_folders.push_back(foldername); _unmapped_folders.push_back(folder);
} }
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); SPIMaster::select_sd(false);
} }
void PlaylistManager::_check_for_special_chars(String s) {
for(int i=0; i<s.length(); i++) {
char c = s.charAt(i);
if (c < 0x20 || c >= 0x7F) {
ERROR("WARNING: Folder / file '%s' contains non-ascii chars!\n", s.c_str());
return;
}
}
}
Playlist* PlaylistManager::get_playlist_for_id(String id) { Playlist* PlaylistManager::get_playlist_for_id(String id) {
if (!_map.count(id)) return NULL; if (!_map.count(id)) return NULL;
String folder = _map[id]; String folder = _map[id];
@ -97,7 +119,7 @@ String PlaylistManager::json() {
json["_type"] = "playlist_manager"; json["_type"] = "playlist_manager";
JsonObject folders = json.createNestedObject("folders"); JsonObject folders = json.createNestedObject("folders");
for (std::map<String, String>::iterator it = _map.begin(); it!=_map.end(); it++) { for (std::map<String, String>::iterator it = _map.begin(); it!=_map.end(); it++) {
folders[it->second] = folders[it->first]; folders[it->second] = it->first;
} }
JsonArray started = json.createNestedArray("started"); JsonArray started = json.createNestedArray("started");
for (std::map<String, Playlist*>::iterator it = _playlists.begin(); it!=_playlists.end(); it++) { for (std::map<String, Playlist*>::iterator it = _playlists.begin(); it!=_playlists.end(); it++) {
@ -112,17 +134,26 @@ String PlaylistManager::json() {
} }
bool PlaylistManager::add_mapping(String id, String folder) { bool PlaylistManager::add_mapping(String id, String folder) {
DEBUG("Adding Mapping: '%s'=>'%s'\n", id.c_str(), folder.c_str()); DEBUG("Adding mapping: %s=>%s\n", id.c_str(), folder.c_str());
if (!SD.exists(folder)) return false;
File ids = SD.open(folder + "/ids.txt", "a");
String data = "\n";
data += id;
data += '\n';
char* buffer = new char[data.length()];
data.toCharArray(buffer, data.length());
ids.write((uint8_t *)buffer, data.length());
delete buffer;
ids.close();
_map[id] = folder; _map[id] = folder;
_save_mapping();
return true; return true;
} }
void PlaylistManager::_save_mapping() {
SPIMaster::select_sd();
File f = SD.open("/_mapping.txt", "w");
String s;
for(std::map<String, String>::iterator it = _map.begin(); it != _map.end(); it++) {
s += it->first;
s += "=";
s += it->second;
s += '\n';
}
unsigned char* buf = new unsigned char[s.length()];
s.getBytes(buf, s.length());
f.write(buf, s.length()-1);
f.close();
SPIMaster::select_sd(false);
delete buf;
}