#include "playlist.h" #include #include #include "AudioTools/CoreAudio/AudioBasic/Collections/Vector.h" // needed for following import (library mistake???= #include "AudioTools/CoreAudio/BaseConverter.h" // needed for following import (library mistake???= #include "AudioTools/AudioLibs/I2SCodecStream.h" bool playlistRepeatOne = false; bool playlistRepeatAll = true; bool playlistRandom = false; String playlistTitle = ""; size_t playlistIndex = 0; std::vector playlistEntries; void playlistClear() { Serial.println("[PLAYLIST ] clear"); playlistTitle = ""; playlistIndex = 0; playlistEntries.clear(); std::vector().swap(playlistEntries); } void playlistAdd(String entry) { entry.trim(); Serial.println("[PLAYLIST ] [ADD] " + entry); const auto index_type_url = entry.indexOf('|'); if (index_type_url < 0) { Serial.println("[PLAYLIST ] type/url-delimiter not found: " + entry); return; } auto type = entry.substring(0, index_type_url); type.trim(); if (type != "TITLE" && type != "ICY" && type != "SD" && type != "SNAP") { Serial.println("[PLAYLIST ] Unknown type: " + type); } entry = entry.substring(index_type_url + 1); entry.trim(); if (type == "TITLE") { playlistTitle = entry; return; } const auto index_url_title = entry.indexOf('|'); if (index_url_title < 0) { Serial.println("[PLAYLIST ] url/title-delimiter not found: " + entry); return; } auto url = entry.substring(0, index_url_title); url.trim(); if (url.isEmpty()) { Serial.println("[PLAYLIST ] url is empty."); return; } auto title = entry.substring(index_url_title + 1); title.trim(); playlistEntries.emplace_back(type, url, title); } void playlistLoad(const String &path) { playlistClear(); Serial.println("[PLAYLIST ] Loading playlist: " + path); if (!SD.begin(PIN_AUDIO_KIT_SD_CARD_CS)) { Serial.println("[PLAYLIST ] Failed to initialize SD card."); return; } if (!SD.exists(path)) { Serial.println("[PLAYLIST ] File not found."); return; } auto file = SD.open(path, FILE_READ); if (!file) { Serial.println("[PLAYLIST ] Failed to open file."); } while (file.available() > 0) { const String entry = file.readStringUntil('\n'); playlistAdd(entry); } file.close(); } Entry playlistSet(const size_t index) { const auto size = playlistEntries.size(); if (size == 0) { return Entry(); } playlistIndex = (index % size + size) % size; return playlistEntries[playlistIndex]; } Entry playlistCurrent() { return playlistSet(playlistIndex); } Entry playlistNext(const int amount) { if (playlistRandom) { return playlistSet(random(static_cast(playlistEntries.size()))); } if (amount < 0 && playlistIndex <= 0 && !playlistRepeatAll) { return Entry(); } if (amount > 0 && playlistIndex >= playlistEntries.size() - 1 && !playlistRepeatAll) { return Entry(); } return playlistSet(playlistIndex + amount); } Entry playlistNextOrRepeatOneIfEnabled() { if (playlistRepeatOne) { return playlistCurrent(); } return playlistNext(+1); } size_t playlistGetCount() { return playlistEntries.size(); } size_t playlistGetIndex() { return playlistIndex; }