diff --git a/include/controller.h b/include/controller.h index a8c5032..7b52d66 100644 --- a/include/controller.h +++ b/include/controller.h @@ -57,4 +57,5 @@ public: String json(); bool process_message(String m); void queue_command(String cmd); + void update_playlist_manager(); }; diff --git a/include/playlist_manager.h b/include/playlist_manager.h index ab2bdd1..188f97a 100644 --- a/include/playlist_manager.h +++ b/include/playlist_manager.h @@ -9,11 +9,14 @@ private: std::map _map; std::map _playlists; std::vector _unmapped_folders; + void _check_for_special_chars(String s); + void _save_mapping(); public: PlaylistManager(); Playlist* get_playlist_for_id(String id); Playlist* get_playlist_for_folder(String folder); void dump_ids(); + void scan_files(); String json(); bool add_mapping(String id, String folder); }; diff --git a/src/controller.cpp b/src/controller.cpp index 6092f51..9e88cb6 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -123,7 +123,8 @@ void Controller::_check_rfid() { } } 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; } int index; @@ -412,5 +413,11 @@ void Controller::inform_new_client(AsyncWebSocketClient* client) { } void Controller::queue_command(String s) { + DEBUG("Enqeueing command '%s'.\n", s.c_str()); _cmd_queue = s; +} + +void Controller::update_playlist_manager() { + _pm->scan_files(); + send_playlist_manager_status(); } \ No newline at end of file diff --git a/src/playlist_manager.cpp b/src/playlist_manager.cpp index 7054fc2..6bb9c67 100644 --- a/src/playlist_manager.cpp +++ b/src/playlist_manager.cpp @@ -4,75 +4,97 @@ #include PlaylistManager::PlaylistManager() { + scan_files(); +} + +void PlaylistManager::scan_files() { SPIMaster::select_sd(); + std::vector folders; File root = SD.open("/"); File entry; while (entry = root.openNextFile()) { String foldername = entry.name(); - if (!entry.isDirectory() || foldername.startsWith("/.")) continue; - // Remove trailing slash + if (foldername.startsWith("/.")) continue; foldername.remove(foldername.length()); - DEBUG(" Checking %s...\n", foldername.c_str()); - bool non_ascii_chars = false; - for(int i=0; i= 0x7F) { - non_ascii_chars = true; + folders.push_back(foldername); + _check_for_special_chars(foldername); + entry.close(); + } + + _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%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::iterator it = _map.begin(); it != _map.end(); it++) { + if (it->second.equals(folder)) { + found = true; break; } } - if (non_ascii_chars) { - ERROR("WARNING: Folder '%s' contains non-ascii chars!\n", foldername.c_str()); - } - - - if (!SD.exists(foldername + "/ids.txt")) { - 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 (!found) { + // Checking folder for media files + File dir = SD.open(folder); + while (entry = dir.openNextFile()) { + String filename = entry.name(); + filename = filename.substring(folder.length() + 1); if (!filename.startsWith(".") && filename.endsWith(".mp3")) { - media_files = true; + found = true; } - file.close(); - if (media_files) break; + entry.close(); + if (found) break; } - if (media_files) { - _unmapped_folders.push_back(foldername); + if (found) { + _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); } +void PlaylistManager::_check_for_special_chars(String s) { + for(int i=0; i= 0x7F) { + ERROR("WARNING: Folder / file '%s' contains non-ascii chars!\n", s.c_str()); + return; + } + } +} + Playlist* PlaylistManager::get_playlist_for_id(String id) { if (!_map.count(id)) return NULL; String folder = _map[id]; @@ -97,7 +119,7 @@ String PlaylistManager::json() { json["_type"] = "playlist_manager"; JsonObject folders = json.createNestedObject("folders"); for (std::map::iterator it = _map.begin(); it!=_map.end(); it++) { - folders[it->second] = folders[it->first]; + folders[it->second] = it->first; } JsonArray started = json.createNestedArray("started"); for (std::map::iterator it = _playlists.begin(); it!=_playlists.end(); it++) { @@ -112,17 +134,26 @@ String PlaylistManager::json() { } bool PlaylistManager::add_mapping(String id, String folder) { - 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(); + DEBUG("Adding mapping: %s=>%s\n", id.c_str(), folder.c_str()); _map[id] = folder; + _save_mapping(); return true; +} + +void PlaylistManager::_save_mapping() { + SPIMaster::select_sd(); + File f = SD.open("/_mapping.txt", "w"); + String s; + for(std::map::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; } \ No newline at end of file