Radio/src/playlist.cpp
2025-06-06 14:20:40 +02:00

134 lines
3.2 KiB
C++

#include "playlist.h"
#include <vector>
#include <SD.h>
#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<Entry> playlistEntries;
void playlistClear() {
Serial.println("[PLAYLIST ] clear");
playlistTitle = "";
playlistIndex = 0;
playlistEntries.clear();
std::vector<Entry>().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<long>(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;
}