Ist wahrscheinlich gar nicht so fürchterlich viel Arbeit.
Eine Playlist, die in std::vector<char*> lebt, sähe rekursiv dann z. B. so aus:
"/mp3_1/titel1",
"/mp3_1/titel2",
"/mp3_1/titel3",
"/mp3_2/titel1",
"/mp3_2/titel2",
"/mp3_2/titel3"
Nehmen wir an, es wird der zweite Titel (/mp3_1/titel2) abgespielt (Index 1), dann müsste man, um in den nächsten Ordner zu kommen, auf den vierten Titel (/mp3_2/titel1) springen (Index 3). Man müsste also schauen, wann sich vorne der Basepath ändert. Dort, wo er sich ändert, das ist der Titel, den wir gerne hätten. Da wollen wir hinspringen. Vorausgesetzt aber immer, dass das Ganze alphabetisch sortiert ist. Das ist Grundvoraussetzung!
Ich habe chatgpt damit mal ein bisschen gefüttert, um ein lauffähiges Beispiel zu kriegen:
#include <iostream>
#include <vector>
#include <string>
int findNextDirectoryTrack(const std::vector<char*>& paths, size_t currentIndex) {
// Überprüfen, ob der aktuelle Index gültig ist
if (currentIndex >= paths.size()) {
return -1; // Ungültiger Index
}
// Extrahiere das Verzeichnis des aktuellen Titels
const char* currentPath = paths[currentIndex];
size_t lastSlashPos = std::string(currentPath).find_last_of('/');
std::string currentDirectory = std::string(currentPath).substr(0, lastSlashPos);
// Iteriere ab dem nächsten Index
for (size_t i = currentIndex + 1; i < paths.size(); ++i) {
const char* path = paths[i];
if (path != nullptr) {
std::string strPath(path);
// Überprüfen, ob das Verzeichnis sich ändert
if (strPath.find(currentDirectory) == std::string::npos) {
return i; // Rückgabe des Index des nächsten Titels im anderen Verzeichnis
}
}
}
// Wenn kein nächster Titel gefunden wurde, gib -1 zurück
return -1;
}
int main() {
std::vector<char*> paths = {
"/mp3_1/titel1",
"/mp3_1/titel2",
"/mp3_1/titel3",
"/mp3_2/titel1",
"/mp3_2/titel2",
"/mp3_2/titel3"
};
size_t currentIndex = 1; // Aktueller Titel (Index)
int nextTrackIndex = findNextDirectoryTrack(paths, currentIndex);
if (nextTrackIndex != -1) {
std::cout << "Nächster Titel Index: " << nextTrackIndex << std::endl;
} else {
std::cout << "Kein nächster Titel gefunden." << std::endl;
}
return 0;
}
Lösungsansatz:
- Es wird ein neuer Playmode gebraucht, dessen Playlist alphabetisch sortiert ist.
- Die Playlist muss jedoch rekursiv generiert werden. Ich glaube allerdings, dass man das in Rekursionstiefe begrenzen muss, so dass das nicht im Desaster endet.
- Man braucht die o.g. Methode (oder was Ähnliches). In die steckt man die Playlist und die aktuelle Abspielposition rein. Gesucht wird dann ab dem Element danach. Die Methode gibt die Indexnummer oder (im Fehlerfalle) -1 zurück.
- Das kann man dann hier einbetten: ESPuino/src/AudioPlayer.cpp at efeb042a3e9ac2514030bc80f61a3938bbc04b7c · biologist79/ESPuino · GitHub. Dort braucht man eine Sonderbehandlung für den neuen Playmode, so dass LASTTRACK zu einem Sprung an die gewünschte Stelle führt. Kann nicht gesprungen werden, so leuchten kurz alle LEDs auf und es wird nicht gesprungen.
Mir fällt aber gerade noch ein, dass das natürlich auch mit Springen rückwärts gehen muss. Da habe ich mit chatgpt jetzt mehrere Iterationen gebraucht, da es sich verrannt hatte. Aber nachdem ich eine Strategie beschrieben habe, kam das raus:
#include <iostream>
#include <vector>
#include <string>
enum class Direction {
Forward,
Backward
};
int findNextDirectoryTrack(const std::vector<char*>& paths, size_t currentIndex, Direction direction) {
// Überprüfen, ob der aktuelle Index gültig ist
if (currentIndex >= paths.size()) {
return -1; // Ungültiger Index
}
// Extrahiere das Verzeichnis des aktuellen Titels
const char* currentPath = paths[currentIndex];
size_t lastSlashPos = std::string(currentPath).find_last_of('/');
std::string currentDirectory = std::string(currentPath).substr(0, lastSlashPos);
if (direction == Direction::Forward) {
// Iteriere ab dem nächsten Index
for (size_t i = currentIndex + 1; i < paths.size(); ++i) {
const char* path = paths[i];
if (path != nullptr) {
std::string strPath(path);
// Überprüfen, ob das Verzeichnis sich ändert
if (strPath.find(currentDirectory) == std::string::npos) {
return i; // Rückgabe des Index des nächsten Titels im anderen Verzeichnis
}
}
}
} else if (direction == Direction::Backward) {
std::string previousDirectory;
// Iteriere rückwärts
for (size_t i = currentIndex; i-- > 0;) {
const char* path = paths[i];
if (path != nullptr) {
std::string strPath(path);
// Überprüfen, ob das Verzeichnis sich ändert
if (strPath.find(currentDirectory) == std::string::npos) {
// Wenn wir das erste andere Verzeichnis gefunden haben, merken wir uns diesen Titel
previousDirectory = strPath.substr(0, strPath.find_last_of('/'));
} else if (!previousDirectory.empty() && strPath.find(previousDirectory) != std::string::npos) {
// Wenn wir wieder in das vorherige Verzeichnis gelangen, geben wir den Index zurück
return i; // Rückgabe des Index des vorherigen Titels im anderen Verzeichnis
}
}
}
// Wenn wir bei 0 angekommen sind, geben wir 0 zurück
return 0; // Immer zum ersten Titel zurückspringen
}
// Wenn kein nächster Titel gefunden wurde, gib -1 zurück
return -1;
}
int main() {
std::vector<char*> paths = {
"/mp3_1/titel1",
"/mp3_1/titel2",
"/mp3_1/titel3",
"/mp3_2/titel1",
"/mp3_2/titel2",
"/mp3_2/titel3"
};
size_t currentIndex = 4; // Aktueller Titel (Index für "/mp3_2/titel2")
// Vorwärts springen
int nextTrackIndexForward = findNextDirectoryTrack(paths, currentIndex, Direction::Forward);
if (nextTrackIndexForward != -1) {
std::cout << "Nächster Titel Index (vorwärts): " << nextTrackIndexForward << std::endl;
} else {
std::cout << "Kein nächster Titel gefunden (vorwärts)." << std::endl;
}
// Rückwärts springen
int nextTrackIndexBackward = findNextDirectoryTrack(paths, currentIndex, Direction::Backward);
if (nextTrackIndexBackward != -1) {
std::cout << "Nächster Titel Index (rückwärts): " << nextTrackIndexBackward << std::endl;
} else {
std::cout << "Kein nächster Titel gefunden (rückwärts)." << std::endl;
}
return 0;
}
- Bei FIRSTTRACK muss man entsprechend rückwärts springen.
Problem mit dem Code-Snippet ist jedoch, dass es rückwärts immer auf 0 springt. Ich habe mal neun Elemente eingefügt und unten eine redimentäre for-Schleife implementiert:
#include <iostream>
#include <string>
#include <vector>
enum class Direction { Forward, Backward };
int findNextDirectoryTrack(const std::vector<char *> &paths,
size_t currentIndex, Direction direction) {
// Überprüfen, ob der aktuelle Index gültig ist
if (currentIndex >= paths.size()) {
return -1; // Ungültiger Index
}
// Extrahiere das Verzeichnis des aktuellen Titels
const char *currentPath = paths[currentIndex];
size_t lastSlashPos = std::string(currentPath).find_last_of('/');
std::string currentDirectory =
std::string(currentPath).substr(0, lastSlashPos);
if (direction == Direction::Forward) {
// Iteriere ab dem nächsten Index
for (size_t i = currentIndex + 1; i < paths.size(); ++i) {
const char *path = paths[i];
if (path != nullptr) {
std::string strPath(path);
// Überprüfen, ob das Verzeichnis sich ändert
if (strPath.find(currentDirectory) == std::string::npos) {
return i; // Rückgabe des Index des nächsten Titels im anderen
// Verzeichnis
}
}
}
} else if (direction == Direction::Backward) {
std::string previousDirectory;
// Iteriere rückwärts
for (size_t i = currentIndex; i-- > 0;) {
const char *path = paths[i];
if (path != nullptr) {
std::string strPath(path);
// Überprüfen, ob das Verzeichnis sich ändert
if (strPath.find(currentDirectory) == std::string::npos) {
// Wenn wir das erste andere Verzeichnis gefunden haben, merken wir
// uns diesen Titel
previousDirectory = strPath.substr(0, strPath.find_last_of('/'));
} else if (!previousDirectory.empty() &&
strPath.find(previousDirectory) != std::string::npos) {
// Wenn wir wieder in das vorherige Verzeichnis gelangen, geben wir
// den Index zurück
return i; // Rückgabe des Index des vorherigen Titels im anderen
// Verzeichnis
}
}
}
// Wenn wir bei 0 angekommen sind, geben wir 0 zurück
return 0; // Immer zum ersten Titel zurückspringen
}
// Wenn kein nächster Titel gefunden wurde, gib -1 zurück
return -1;
}
int main() {
std::vector<char *> paths = {
"/mp3_0/titel1", "/mp3_0/titel2", "/mp3_0/titel3",
"/mp3_1/titel1", "/mp3_1/titel2", "/mp3_1/titel3",
"/mp3_2/titel1", "/mp3_2/titel2", "/mp3_2/titel3"};
for (int i = 0; i < 9; i++) {
size_t currentIndex = i; // Aktueller Titel (Index für "/mp3_2/titel2")
// Vorwärts springen
int nextTrackIndexForward =
findNextDirectoryTrack(paths, currentIndex, Direction::Forward);
if (nextTrackIndexForward != -1) {
std::cout << i
<< " Nächster Titel Index (vorwärts): " << nextTrackIndexForward
<< std::endl;
} else {
std::cout << i << " Kein nächster Titel gefunden (vorwärts)."
<< std::endl;
}
// Rückwärts springen
int nextTrackIndexBackward =
findNextDirectoryTrack(paths, currentIndex, Direction::Backward);
if (nextTrackIndexBackward != -1) {
std::cout << i << " Nächster Titel Index (rückwärts): "
<< nextTrackIndexBackward << std::endl;
} else {
std::cout << i << " Kein nächster Titel gefunden (rückwärts)."
<< std::endl;
}
}
return 0;
}
Die Ausgabe ist:
0 Nächster Titel Index (vorwärts): 3
0 Nächster Titel Index (rückwärts): 0
1 Nächster Titel Index (vorwärts): 3
1 Nächster Titel Index (rückwärts): 0
2 Nächster Titel Index (vorwärts): 3
2 Nächster Titel Index (rückwärts): 0
3 Nächster Titel Index (vorwärts): 6
3 Nächster Titel Index (rückwärts): 0
4 Nächster Titel Index (vorwärts): 6
4 Nächster Titel Index (rückwärts): 0
5 Nächster Titel Index (vorwärts): 6
5 Nächster Titel Index (rückwärts): 0
6 Kein nächster Titel gefunden (vorwärts).
6 Nächster Titel Index (rückwärts): 0
7 Kein nächster Titel gefunden (vorwärts).
7 Nächster Titel Index (rückwärts): 0
8 Kein nächster Titel gefunden (vorwärts).
8 Nächster Titel Index (rückwärts): 0
Ich habe jetzt heute keinen Nerv mehr, drüber nachzudenken 
Also vorwärts passt alles. Aber rückwärts halt (noch) nicht. Erwarten würde man (ich)
0+1+2 => 0 (aktuelles Hörspiel beginnt von vorne)
3+4+5 => 0 (Sprung auf voriges Hörspiel)
6+7+8: => 3 (Sprung auf voriges Hörspiel)