Directories working, web interface
This commit is contained in:
parent
2dd95a35eb
commit
f173272f8b
|
|
@ -116,31 +116,72 @@ DirectoryNode *DirectoryNode::findFirstDirectoryWithMP3s()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void DirectoryNode::advanceToNextMP3()
|
||||
void DirectoryNode::advanceToFirstMP3InThisNode() {
|
||||
if (mp3Files.size()>0) {
|
||||
currentPlaying = &mp3Files[0];
|
||||
}
|
||||
}
|
||||
|
||||
DirectoryNode* DirectoryNode::advanceToNextMP3(const String* currentGlobal)
|
||||
{
|
||||
if (currentPlaying != nullptr)
|
||||
bool useFirst = false;
|
||||
Serial.println(currentGlobal->c_str());
|
||||
if (currentGlobal != nullptr)
|
||||
{
|
||||
for (size_t i = 0; i < mp3Files.size(); i++)
|
||||
{
|
||||
if (*currentPlaying == mp3Files[i])
|
||||
if (*currentGlobal == mp3Files[i])
|
||||
{
|
||||
// Found the current playing MP3 file
|
||||
if (i < mp3Files.size() - 1)
|
||||
{
|
||||
// Advance to the next MP3 file in the same directory
|
||||
currentPlaying = &mp3Files[i + 1];
|
||||
return;
|
||||
return this;
|
||||
}
|
||||
useFirst = true;
|
||||
// Reached the end of the MP3 files in the directory
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We are either not playing, or we've exhausted all the MP3 files in this directory.
|
||||
// Therefore, we need to recursively look in our subdirectories.
|
||||
for (auto subdir : subdirectories)
|
||||
{
|
||||
Serial.println("searching next node");
|
||||
|
||||
if (useFirst && subdir->mp3Files.size()>0) {
|
||||
subdir->currentPlaying = &subdir->mp3Files[0];
|
||||
return subdir;
|
||||
}
|
||||
|
||||
// Have each subdirectory advance its song
|
||||
for (size_t i = 0; i < subdir->mp3Files.size(); i++)
|
||||
{
|
||||
if (*currentGlobal == subdir->mp3Files[i])
|
||||
{
|
||||
// Found the current playing MP3 file
|
||||
if (i < subdir->mp3Files.size() - 1)
|
||||
{
|
||||
// Advance to the next MP3 file in the same directory
|
||||
subdir->currentPlaying = &subdir->mp3Files[i + 1];
|
||||
return subdir;
|
||||
} else {
|
||||
useFirst = true;
|
||||
}
|
||||
// Reached the end of the MP3 files in the directory
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If not playing or reached the end, set the first MP3 file as the current playing
|
||||
if (!mp3Files.empty())
|
||||
{
|
||||
currentPlaying = &mp3Files[0];
|
||||
}
|
||||
|
||||
// If we get here, there were no MP3 files or subdirectories left to check
|
||||
currentPlaying = nullptr;
|
||||
Serial.println("no more nodes found");
|
||||
return this;
|
||||
}
|
||||
|
||||
String DirectoryNode::getDirectoryStructureHTML() const
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ public:
|
|||
void addMP3File(const String& mp3File);
|
||||
void buildDirectoryTree(const char* currentPath);
|
||||
void printDirectoryTree(int level = 0) const;
|
||||
void advanceToNextMP3();
|
||||
DirectoryNode* advanceToNextMP3(const String* currentGlobal);
|
||||
void advanceToFirstMP3InThisNode();
|
||||
String getDirectoryStructureHTML() const;
|
||||
void appendIndentation(String& html, int level) const;
|
||||
DirectoryNode* findFirstDirectoryWithMP3s();
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ const char index_html[] PROGMEM = R"rawliteral(
|
|||
<title>HannaBox</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body { font-family: Arial; text-align: center; margin:0px auto; padding-top: 30px;}
|
||||
body { font-family: Arial; margin:5px auto; padding: 30px;}
|
||||
.button {
|
||||
padding: 10px 20px;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
outline: none;
|
||||
color: #fff;
|
||||
background-color: #2f4468;
|
||||
|
|
@ -36,9 +35,15 @@ const char index_html[] PROGMEM = R"rawliteral(
|
|||
<body>
|
||||
<h1>HannaBox</h1>
|
||||
|
||||
Playing %PLAYING%<br/><br/>
|
||||
<button class="button" onmouseup="toggleCheckbox('start');" ontouchend="toggleCheckbox('start');">On!</button><br/><br/>
|
||||
<button class="button" onmouseup="toggleCheckbox('stop');" ontouchend="toggleCheckbox('stop');">Off!</button><br/><br/>
|
||||
<span id="state">%PLAYING%</span><br/><br/>
|
||||
<button class="button" onmouseup="toggleCheckbox('start');" ontouchend="toggleCheckbox('start');">Start</button><br/><br/>
|
||||
<button class="button" onmouseup="toggleCheckbox('stop');" ontouchend="toggleCheckbox('stop');">Stop</button><br/><br/>
|
||||
<button class="button" onmouseup="toggleCheckbox('next');" ontouchend="toggleCheckbox('next');">Next</button><br/><br/>
|
||||
<p>
|
||||
<h2>Content of SD Card:</h2>
|
||||
%DIRECTORY%
|
||||
</p>
|
||||
|
||||
<script>
|
||||
setInterval(getState, 500);
|
||||
function toggleCheckbox(x) {
|
||||
|
|
|
|||
154
src/main.cpp
154
src/main.cpp
|
|
@ -1,11 +1,11 @@
|
|||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
|
||||
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
#include <ESPAsyncWebServer.h> //Local WebServer used to serve the configuration portal
|
||||
#include <ESPAsyncWiFiManager.h> //https://github.com/tzapu/WiFiManager WiFi Configuration Magic
|
||||
#include <ESPAsyncWebServer.h> //Local WebServer used to serve the configuration portal
|
||||
#include <ESPAsyncWiFiManager.h> //https://github.com/tzapu/WiFiManager WiFi Configuration Magic
|
||||
|
||||
#include "Audio.h"
|
||||
|
||||
|
|
@ -30,41 +30,34 @@ Audio audio;
|
|||
|
||||
AsyncWebServer server(80);
|
||||
DNSServer dns;
|
||||
File next;
|
||||
|
||||
|
||||
|
||||
DirectoryNode rootNode("/");
|
||||
DirectoryNode* currentNode = NULL;
|
||||
DirectoryNode *currentNode = NULL;
|
||||
|
||||
void stop();
|
||||
|
||||
void start();
|
||||
|
||||
|
||||
void playNextMp3()
|
||||
{
|
||||
next = root.openNextFile();
|
||||
|
||||
if (!next)
|
||||
stop();
|
||||
if (currentNode == NULL)
|
||||
{
|
||||
root = SD.open("/");
|
||||
}
|
||||
|
||||
while (!String(next.name()).endsWith(".mp3"))
|
||||
{
|
||||
next = root.openNextFile();
|
||||
if (!next)
|
||||
currentNode = rootNode.findFirstDirectoryWithMP3s();
|
||||
if (currentNode)
|
||||
{
|
||||
Serial.println("no more files found.");
|
||||
return;
|
||||
currentNode->advanceToFirstMP3InThisNode();
|
||||
}
|
||||
}
|
||||
Serial.print("initialized");
|
||||
Serial.print(next.name());
|
||||
Serial.print("\n");
|
||||
audio.stopSong();
|
||||
audio.connecttoSD(next.name());
|
||||
else
|
||||
{
|
||||
currentNode = rootNode.advanceToNextMP3(currentNode->getCurrentPlaying());
|
||||
}
|
||||
Serial.print("Now advancing to ");
|
||||
String mp3File = currentNode->getCurrentPlayingFilePath();
|
||||
Serial.println(mp3File.c_str());
|
||||
|
||||
audio.connecttoSD(mp3File.c_str());
|
||||
}
|
||||
|
||||
void audio_info(const char *info)
|
||||
|
|
@ -72,25 +65,57 @@ void audio_info(const char *info)
|
|||
// Serial.print("info "); Serial.println(info);
|
||||
}
|
||||
|
||||
String processor(const String& var)
|
||||
String getState()
|
||||
{
|
||||
if(var == "PLAYING")
|
||||
return F(next.name());
|
||||
String state = String();
|
||||
if (audio.isRunning())
|
||||
{
|
||||
state += "Playing ";
|
||||
}
|
||||
else
|
||||
{
|
||||
state += "Stopped ";
|
||||
}
|
||||
if (currentNode)
|
||||
{
|
||||
state += currentNode->getName();
|
||||
state += " ";
|
||||
if (currentNode->getCurrentPlaying())
|
||||
state += *currentNode->getCurrentPlaying();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
String processor(const String &var)
|
||||
{
|
||||
if (var == "PLAYING" && currentNode)
|
||||
return getState();
|
||||
if (var == "DIRECTORY")
|
||||
{
|
||||
return rootNode.getDirectoryStructureHTML();
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
void stop() {
|
||||
if (audio.isRunning()) {
|
||||
void stop()
|
||||
{
|
||||
Serial.println("stopping audio.");
|
||||
if (audio.isRunning())
|
||||
{
|
||||
audio.stopSong();
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
if (!next) {
|
||||
playNextMp3();
|
||||
} else {
|
||||
audio.connecttoSD(next.name());
|
||||
}
|
||||
void start()
|
||||
{
|
||||
currentNode->setCurrentPlaying(NULL);
|
||||
currentNode = NULL;
|
||||
playNextMp3();
|
||||
}
|
||||
|
||||
void next()
|
||||
{
|
||||
playNextMp3();
|
||||
}
|
||||
|
||||
void setup()
|
||||
|
|
@ -117,56 +142,51 @@ void setup()
|
|||
|
||||
rootNode.buildDirectoryTree("/");
|
||||
rootNode.printDirectoryTree();
|
||||
//printDirectoryTree(&rootNode, 0);
|
||||
|
||||
// printDirectoryTree(&rootNode, 0);
|
||||
|
||||
// printDirectory(root, 0);
|
||||
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
|
||||
audio.setVolume(12); // 0...21
|
||||
|
||||
|
||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||
{ request->send_P(200, "text/html", index_html,processor); });
|
||||
{ request->send_P(200, "text/html", index_html, processor); });
|
||||
|
||||
server.on("/start", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
start();
|
||||
request->send(200, "text/plain", "start");
|
||||
});
|
||||
server.on("/state", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||
{
|
||||
String state = getState();
|
||||
request->send(200, "text/plain", state.c_str()); });
|
||||
|
||||
server.on("/start", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||
{
|
||||
|
||||
request->send(200, "text/plain", "start");
|
||||
start(); });
|
||||
|
||||
server.on("/stop", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||
{
|
||||
|
||||
request->send(200, "text/plain", "stop");
|
||||
stop(); });
|
||||
|
||||
server.on("/next", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||
{
|
||||
|
||||
request->send(200, "text/plain", "next");
|
||||
next(); });
|
||||
|
||||
server.on("/stop", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
stop();
|
||||
request->send(200, "text/plain", "stop");
|
||||
});
|
||||
|
||||
server.begin();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
audio.loop();
|
||||
// Serial.print(digitalRead(D2));
|
||||
|
||||
if (digitalRead(D3) == LOW)
|
||||
{
|
||||
unsigned long now = millis();
|
||||
if (now - lastStart > startDelay)
|
||||
{
|
||||
if (currentNode==NULL) {
|
||||
currentNode = rootNode.findFirstDirectoryWithMP3s();
|
||||
if (currentNode) {
|
||||
currentNode->advanceToNextMP3();
|
||||
}
|
||||
} else {
|
||||
currentNode->advanceToNextMP3();
|
||||
}
|
||||
Serial.print("Now advancing to ");
|
||||
String mp3File = currentNode->getCurrentPlayingFilePath();
|
||||
Serial.println(mp3File.c_str());
|
||||
audio.connecttoSD(mp3File.c_str());
|
||||
Serial.println("mp3 started.");
|
||||
playNextMp3();
|
||||
lastStart = now;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue