#include "playlist_manager.h" #include #include "spi_master.h" #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 (foldername.startsWith("/.")) continue; foldername.remove(foldername.length()); 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 (!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")) { found = true; } entry.close(); if (found) break; } if (found) { _unmapped_folders.push_back(folder); } } } 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]; return get_playlist_for_folder(folder); } Playlist* PlaylistManager::get_playlist_for_folder(String folder) { if (!_playlists.count(folder)) { _playlists[folder] = new Playlist(folder); } return _playlists[folder]; } void PlaylistManager::dump_ids() { for (std::map::iterator it = _map.begin(); it!=_map.end(); it++) { INFO(" %s -> %s\n", it->first.c_str(), it->second.c_str()); } } String PlaylistManager::json() { DynamicJsonDocument json(10240); json["_type"] = "playlist_manager"; JsonObject folders = json.createNestedObject("folders"); for (std::map::iterator it = _map.begin(); it!=_map.end(); it++) { folders[it->second] = it->first; } JsonArray started = json.createNestedArray("started"); for (std::map::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(); } bool PlaylistManager::add_mapping(String id, String folder) { 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 = create_mapping_txt(); 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; } String PlaylistManager::create_mapping_txt() { String s; for(std::map::iterator it = _map.begin(); it != _map.end(); it++) { s += it->first; s += "="; s += it->second; s += '\n'; } return s; }