134 lines
3.2 KiB
C++
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;
|
|
}
|