diff --git a/src/audio.cpp b/src/audio.cpp index dd32d35..f517e46 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -11,6 +11,10 @@ #include "SnapClient.h" #include "wifi.h" +bool audioMute = false; + +float audioVolume = 0.05; + AudioBoardStream board(AudioKitEs8388V1); File file; @@ -188,6 +192,9 @@ void audioSetup() { } bool audioLoop() { + audioVolume = max(0.0f, min(audioVolume, 1.0f)); + board.setVolume(audioVolume); + board.setMute(audioMute); if (copier.copy() > 0) { return true; } diff --git a/src/audio.h b/src/audio.h index 50ce6bf..65b0a2c 100644 --- a/src/audio.h +++ b/src/audio.h @@ -3,6 +3,10 @@ #include "playlist.h" +extern bool audioMute; + +extern float audioVolume; + bool audioPlay(const Entry &entry); void audioStop(); diff --git a/src/http.cpp b/src/http.cpp new file mode 100644 index 0000000..3247bce --- /dev/null +++ b/src/http.cpp @@ -0,0 +1,57 @@ +#include "http.h" + +#include "audio.h" +#include "ESPAsyncWebServer.h" +#include "player.h" + +AsyncWebServer server(80); + +void httpSetup() { + Serial.println("Starting HTTP server"); + DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); + server.onNotFound([](AsyncWebServerRequest *request) { + const auto path = request->url(); + if (path.endsWith("/") && path.length() > 1) { + request->redirect(path.substring(0, path.length() - 1)); + } else { + request->send(404, "text/plain", "Not Found"); + } + }); + server.on("/player/stop", [](AsyncWebServerRequest *request) { + playerState = PLAYER_STOP; + request->send(200); + }); + server.on("/player/play", [](AsyncWebServerRequest *request) { + playerState = PLAYER_PLAY; + request->send(200); + }); + server.on("/player/pause", [](AsyncWebServerRequest *request) { + playerState = PLAYER_PAUSE; + request->send(200); + }); + server.on("/player/mute", [](AsyncWebServerRequest *request) { + audioMute = true; + request->send(200); + }); + server.on("/player/unmute", [](AsyncWebServerRequest *request) { + audioMute = false; + request->send(200); + }); + server.on("/player/up", [](AsyncWebServerRequest *request) { + audioVolume = max(0.0f, min(audioVolume + 0.05f, 1.0f)); + request->send(200); + }); + server.on("/player/down", [](AsyncWebServerRequest *request) { + audioVolume = max(0.0f, min(audioVolume - 0.05f, 1.0f)); + request->send(200); + }); + server.on("/player/next", [](AsyncWebServerRequest *request) { + playerSkip += 1; + request->send(200); + }); + server.on("/player/back", [](AsyncWebServerRequest *request) { + playerSkip -= 1; + request->send(200); + }); + server.begin(); +} diff --git a/src/http.h b/src/http.h new file mode 100644 index 0000000..abcba1f --- /dev/null +++ b/src/http.h @@ -0,0 +1,6 @@ +#ifndef HTTP_H +#define HTTP_H + +void httpSetup(); + +#endif diff --git a/src/main.cpp b/src/main.cpp index 0feb8b4..2cc268b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include +#include "http.h" #include "wifi.h" #include "player.h" #include "playlist.h" @@ -13,6 +14,9 @@ void setup() { playlistClear(); playlistAdd("ICY|http://liveradio.sr.de/sr/sr1/mp3/128/stream.mp3|SR1"); playlistAdd("ICY|https://stream.rockantenne.de/rockantenne/stream/mp3|Rockantenne Classic Perlen"); + + wifiLoop(); + httpSetup(); } void loop() { diff --git a/src/player.cpp b/src/player.cpp index 108468d..db6debc 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -12,19 +12,15 @@ unsigned long errorMs = 0; unsigned long delayMs = 0; +int playerSkip = 0; + +PlayerState playerState = PLAYER_STOP; + void playerSetup() { audioSetup(); } -void playerLoop() { - if (audioLoop()) { - errorMs = 0; - return; - } - if (errorMs > 0 && millis() - errorMs < delayMs) { - return; - } - const auto entry = playlistNextOrRepeatOneIfEnabled(); +void playerPlay(const Entry entry) { if (audioPlay(entry)) { errorMs = 0; delayMs = 0; @@ -34,3 +30,20 @@ void playerLoop() { Serial.printf("retry delay: %d ms\n", delayMs); } } + +void playerLoop() { + if (playerSkip != 0) { + const auto entry = playlistNext(playerSkip); + playerPlay(entry); + playerSkip = 0; + } + if (audioLoop()) { + errorMs = 0; + return; + } + if (errorMs > 0 && millis() - errorMs < delayMs) { + return; + } + const auto entry = playlistNextOrRepeatOneIfEnabled(); + playerPlay(entry); +} diff --git a/src/player.h b/src/player.h index c280aa6..f3d2a6a 100644 --- a/src/player.h +++ b/src/player.h @@ -1,6 +1,16 @@ #ifndef PLAYER_H #define PLAYER_H +enum PlayerState { + PLAYER_STOP, + PLAYER_PLAY, + PLAYER_PAUSE, +}; + +extern PlayerState playerState; + +extern int playerSkip; + void playerSetup(); void playerLoop(); diff --git a/src/playlist.cpp b/src/playlist.cpp index 896811d..c0bae24 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -102,21 +102,24 @@ Entry playlistCurrent() { return playlistSet(playlistIndex); } -Entry playlistNext() { - if (playlistIndex >= playlistEntries.size() - 1 && !playlistRepeatAll) { +Entry playlistNext(const int amount) { + if (amount < 0 && playlistIndex <= 0 && !playlistRepeatAll) { return Entry(); } - return playlistSet(playlistIndex + 1); + if (amount > 0 && playlistIndex >= playlistEntries.size() - 1 && !playlistRepeatAll) { + return Entry(); + } + return playlistSet(playlistIndex + amount); } Entry playlistNextOrRepeatOneIfEnabled() { if (playlistRepeatOne) { return playlistCurrent(); } - return playlistNext(); + return playlistNext(+1); } -Entry playlistPrevious() { +Entry playlistBack() { if (playlistIndex <= 0 && !playlistRepeatAll) { return Entry(); } diff --git a/src/playlist.h b/src/playlist.h index c0278d6..67f52f0 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -11,10 +11,10 @@ void playlistLoad(const String &path); Entry playlistCurrent(); -Entry playlistNext(); +Entry playlistNext(int amount); Entry playlistNextOrRepeatOneIfEnabled(); -Entry playlistPrevious(); +Entry playlistBack(); #endif