@@ -33,13 +33,12 @@ const char* NOTHING_PLAYING_STR {
3333const char * VOLUME_HEADER {
3434 " volume\n "
3535};
36+
3637const char * CURRENT_HEADER {" currentPLitem\n " };
3738const char * MESSAGE_HEADER {" message\n " };
3839
3940int currentItem {NOTHING_PLAYING_VAL };
4041
41- bool volumeIsUpdated{false };
42-
4342playList_t playList;
4443AsyncWebServer server (80 );
4544AsyncWebSocket ws (" /ws" );
@@ -120,28 +119,6 @@ struct {
120119 uint32_t clientId;
121120} newUrl;
122121
123- struct {
124- bool requested{false };
125- String filename;
126- uint32_t clientId;
127- } currentToFavorites;
128-
129- struct {
130- bool updated{false };
131- } favorites;
132-
133- struct {
134- bool requested{false };
135- String name;
136- bool startNow;
137- } favoriteToPlaylist;
138-
139- struct {
140- bool requested{false };
141- String name;
142- uint32_t clientId;
143- } deletefavorite;
144-
145122time_t bootTime;
146123
147124inline __attribute__ ((always_inline))
@@ -191,6 +168,12 @@ void playListHasEnded() {
191168#endif // M5STACK_NODE
192169}
193170
171+ void updateFavoritesOnClients () {
172+ String s;
173+ ws.textAll (favoritesToString (s));
174+ ESP_LOGD (TAG , " Favorites and clients are updated." );
175+ }
176+
194177static char showstation[200 ]; // These are kept global to update new clients in loop()
195178void audio_showstation (const char *info) {
196179 if (!strcmp (info, " " )) return ;
@@ -259,7 +242,7 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
259242 if (pch) {
260243 const uint8_t volume = atoi (pch);
261244 audio.setVolume (volume > I2S_MAX_VOLUME ? I2S_MAX_VOLUME : volume);
262- volumeIsUpdated = true ;
245+ ws. textAll ( VOLUME_HEADER + String (audio. getVolume ())) ;
263246 }
264247 return ;
265248 }
@@ -276,6 +259,9 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
276259 }
277260 ESP_LOGD (TAG , " Added %i items to playlist" , playList.size () - previousSize);
278261 client->printf (" %sAdded %i items to playlist" , MESSAGE_HEADER , playList.size () - previousSize);
262+
263+ if (!playList.isUpdated ) return ;
264+
279265 if (startnow) {
280266 if (audio.isRunning ()) muteVolumeAndStopAudio ();
281267 currentItem = previousSize - 1 ;
@@ -397,26 +383,30 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
397383
398384 else if (!strcmp (" currenttofavorites" , pch)) {
399385 pch = strtok (NULL , " \n " );
400- if (pch) {
401- currentToFavorites.filename = pch;
402- currentToFavorites.clientId = client->id ();
403- currentToFavorites.requested = true ;
404- }
386+ if (pch)
387+ handleCurrentToFavorites ((String)pch, client->id ());
405388 return ;
406389 }
407390
408391 else if (!strcmp (" favoritetoplaylist" , pch) ||
409392 !strcmp (" _favoritetoplaylist" , pch)) {
410- const bool startnow = (pch[0 ] == ' _' );
411- favoriteToPlaylist. name = strtok (NULL , " \n " );
412- favoriteToPlaylist. startNow = startnow;
413- favoriteToPlaylist. requested = true ;
393+ const bool startNow = (pch[0 ] == ' _' );
394+ pch = strtok (NULL , " \n " );
395+ if (pch)
396+ handleFavoriteToPlaylist ((String)pch, startNow) ;
414397 return ;
415398 }
416399
417400 else if (!strcmp (" deletefavorite" , pch)) {
418- deletefavorite.name = strtok (NULL , " \n " );
419- deletefavorite.requested = true ;
401+ pch = strtok (NULL , " \n " );
402+ if (pch) {
403+ if (!FFat.remove (" /" + (String)pch)) {
404+ ws.printf (client->id (), " %sCould not delete %s" , MESSAGE_HEADER , pch);
405+ } else {
406+ ws.printfAll (" %sDeleted favorite %s" , MESSAGE_HEADER , pch);
407+ updateFavoritesOnClients ();
408+ }
409+ }
420410 return ;
421411 }
422412
@@ -426,8 +416,12 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
426416 const uint32_t index = atoi (strtok (NULL , " \n " ));
427417 if (index < sizeof (preset) / sizeof (source)) { // only add really existing presets to the playlist
428418 playList.add ({HTTP_PRESET , " " , " " , index});
419+
420+ if (!playList.isUpdated ) return ;
421+
429422 ESP_LOGD (TAG , " Added '%s' to playlist" , preset[index].name .c_str ());
430423 client->printf (" %sAdded '%s' to playlist" , MESSAGE_HEADER , preset[index].name .c_str ());
424+
431425 if (startnow) {
432426 if (audio.isRunning ()) muteVolumeAndStopAudio ();
433427 currentItem = playList.size () - 2 ;
@@ -500,9 +494,13 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
500494 }
501495 delete [] buffer;
502496 buffer = nullptr ;
497+
503498 ESP_LOGD (TAG , " Added %i items to playlist" , playList.size () - previousSize);
504499
505500 client->printf (" %sAdded %i items to playlist" , MESSAGE_HEADER , playList.size () - previousSize);
501+
502+ if (!playList.isUpdated ) return ;
503+
506504 if (startnow) {
507505 if (audio.isRunning ()) muteVolumeAndStopAudio ();
508506 currentItem = previousSize - 1 ;
@@ -523,7 +521,7 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
523521
524522const char * HEADER_MODIFIED_SINCE = " If-Modified-Since" ;
525523
526- static inline __attribute__ ((always_inline)) bool htmlUnmodified(const AsyncWebServerRequest* request, const char * date) {
524+ static inline __attribute__ ((always_inline)) bool htmlUnmodified(const AsyncWebServerRequest * request, const char * date) {
527525 return request->hasHeader (HEADER_MODIFIED_SINCE ) && request->header (HEADER_MODIFIED_SINCE ).equals (date);
528526}
529527
@@ -783,7 +781,7 @@ void setup() {
783781 audio.setVolume (I2S_INITIAL_VOLUME );
784782}
785783
786- String& favoritesToString (String& s) {
784+ String& favoritesToString (String & s) {
787785 File root = FFat.open (" /" );
788786 s = " " ;
789787 if (!root || !root.isDirectory ()) {
@@ -802,7 +800,7 @@ String& favoritesToString(String& s) {
802800 return s;
803801}
804802
805- bool startPlaylistItem (const playListItem& item) {
803+ bool startPlaylistItem (const playListItem & item) {
806804 switch (item.type ) {
807805 case HTTP_FILE :
808806 ESP_LOGD (TAG , " STARTING file: %s" , item.url .c_str ());
@@ -837,7 +835,7 @@ bool startPlaylistItem(const playListItem& item) {
837835 return audio.isRunning ();
838836}
839837
840- bool saveItemToFavorites (const playListItem& item, const String& filename) {
838+ bool saveItemToFavorites (const playListItem & item, const String & filename) {
841839 switch (item.type ) {
842840 case HTTP_FILE :
843841 ESP_LOGD (TAG , " file (wont save)%s" , item.url .c_str ());
@@ -860,9 +858,7 @@ bool saveItemToFavorites(const playListItem& item, const String& filename) {
860858 ESP_LOGE (TAG , " failed to open file for writing" );
861859 return false ;
862860 }
863- audio.loop ();
864861 bool result = file.print (item.url .c_str ());
865- audio.loop ();
866862 file.close ();
867863 ESP_LOGD (TAG , " %s writing to '%s'" , result ? " ok" : " WARNING - failed" , filename);
868864 return result;
@@ -877,14 +873,23 @@ bool saveItemToFavorites(const playListItem& item, const String& filename) {
877873}
878874
879875void handlePastedUrl () {
876+
877+ if (playList.size () > PLAYLIST_MAX_ITEMS - 1 ) {
878+ char buffer[50 ];
879+ snprintf (buffer, sizeof (buffer), " %sPlaylist is full." , MESSAGE_HEADER );
880+ ws.text (newUrl.clientId , buffer);
881+ return ;
882+ }
883+
880884 ESP_LOGI (TAG , " STARTING new url: %s with %i items in playList" , newUrl.url .c_str (), playList.size ());
881885 muteVolumeAndStopAudio ();
882886 audio_showstreamtitle (" starting new stream" );
883887 audio_showstation (" " );
884888 const playListItem item {HTTP_STREAM , newUrl.url , newUrl.url };
885889 if (startPlaylistItem (item)) {
886- ESP_LOGI (TAG , " url started successful" );
890+ ESP_LOGD (TAG , " url started successful" );
887891 playList.add (item);
892+
888893 currentItem = playList.size () - 1 ;
889894 playerStatus = PLAYING ;
890895 audio_showstation (newUrl.url .c_str ());
@@ -903,23 +908,26 @@ void handlePastedUrl() {
903908 }
904909}
905910
906- void handleFavoriteToPlaylist () {
907- File file = FFat.open (" /" + favoriteToPlaylist. name );
911+ void handleFavoriteToPlaylist (const String& filename, const bool startNow ) {
912+ File file = FFat.open (" /" + filename );
908913 String url;
909914 if (file) {
910915 while (file.available () && (file.peek () != ' \n ' ) && url.length () < 1024 ) /* only read the first line and limit the size of the resulting string - unknown/leftover files might contain garbage*/
911916 url += (char )file.read ();
912917 file.close ();
913918 }
914919 else {
915- ESP_LOGE (TAG , " Could not open %s" , favoriteToPlaylist. name .c_str ());
916- ws.printfAll (" %sCould not add '%s' to playlist" , MESSAGE_HEADER , favoriteToPlaylist. name .c_str ());
920+ ESP_LOGE (TAG , " Could not open %s" , filename .c_str ());
921+ ws.printfAll (" %sCould not add '%s' to playlist" , MESSAGE_HEADER , filename .c_str ());
917922 return ;
918923 }
919- playList.add ({HTTP_FAVORITE , favoriteToPlaylist.name , url});
920- ESP_LOGD (TAG , " favorite to playlist: %s -> %s" , favoriteToPlaylist.name .c_str (), url.c_str ());
921- ws.printfAll (" %sAdded '%s' to playlist" , MESSAGE_HEADER , favoriteToPlaylist.name .c_str ());
922- if (favoriteToPlaylist.startNow ) {
924+ playList.add ({HTTP_FAVORITE , filename, url});
925+
926+ if (!playList.isUpdated ) return ;
927+
928+ ESP_LOGD (TAG , " favorite to playlist: %s -> %s" , filename.c_str (), url.c_str ());
929+ ws.printfAll (" %sAdded '%s' to playlist" , MESSAGE_HEADER , filename.c_str ());
930+ if (startNow) {
923931 if (audio.isRunning ()) muteVolumeAndStopAudio ();
924932 currentItem = playList.size () - 2 ;
925933 playerStatus = PLAYING ;
@@ -931,31 +939,16 @@ void handleFavoriteToPlaylist() {
931939 }
932940}
933941
934- void handlePlaylistUpdate () {
935- String s;
936- ws.textAll (playList.toString (s));
937- updateHighlightedItemOnClients ();
938-
939- #if defined (M5STACK_NODE)
940- M5_displayCurrentAndTotal ();
941- #endif
942-
943- ESP_LOGD (TAG , " Playlist updated. %i items. Free mem: %i" , playList.size (), ESP .getFreeHeap ());
944- }
945-
946- void handleCurrentToFavorites () {
942+ void handleCurrentToFavorites (const String & filename, const uint32_t clientId) {
947943 playListItem item;
948944 playList.get (currentItem, item);
949945
950- if (saveItemToFavorites (item, currentToFavorites.filename )) {
951- String s;
952- ws.textAll (favoritesToString (s));
953- ws.printfAll (" %sAdded '%s' to favorites!" , MESSAGE_HEADER , currentToFavorites.filename .c_str ());
946+ if (saveItemToFavorites (item, filename)) {
947+ ws.printfAll (" %sAdded '%s' to favorites!" , MESSAGE_HEADER , filename.c_str ());
948+ updateFavoritesOnClients ();
954949 }
955950 else
956- ws.printf (currentToFavorites.clientId , " %sSaving failed!" , MESSAGE_HEADER );
957-
958- currentToFavorites.filename = " " ;
951+ ws.printf (clientId, " %sSaving '%s' failed!" , MESSAGE_HEADER , filename.c_str ());
959952}
960953
961954void startCurrentItem () {
@@ -978,47 +971,26 @@ void startCurrentItem() {
978971void handleWebsocketClients () {
979972 ws.cleanupClients ();
980973
981- if (volumeIsUpdated) {
982- ws.textAll (VOLUME_HEADER + String (audio.getVolume ()));
983- volumeIsUpdated = false ;
984- }
985-
986974 if (playList.isUpdated ) {
987- handlePlaylistUpdate ();
975+ {
976+ String s;
977+ ws.textAll (playList.toString (s));
978+ }
979+ updateHighlightedItemOnClients ();
980+
981+ #if defined (M5STACK_NODE)
982+ M5_displayCurrentAndTotal ();
983+ #endif
984+
985+ ESP_LOGD (TAG , " Playlist updated. %i items. Free mem: %i" , playList.size (), ESP .getFreeHeap ());
986+
988987 playList.isUpdated = false ;
989988 }
990989
991990 if (newUrl.waiting ) {
992991 handlePastedUrl ();
993992 newUrl.waiting = false ;
994993 }
995-
996- if (favoriteToPlaylist.requested ) {
997- handleFavoriteToPlaylist ();
998- favoriteToPlaylist.requested = false ;
999- }
1000-
1001- if (currentToFavorites.requested ) {
1002- handleCurrentToFavorites ();
1003- currentToFavorites.requested = false ;
1004- }
1005-
1006- if (deletefavorite.requested ) {
1007- if (!FFat.remove (" /" + deletefavorite.name )) {
1008- ws.printf (deletefavorite.clientId , " %sCould not delete %s" , MESSAGE_HEADER , deletefavorite.name .c_str ());
1009- } else {
1010- ws.printfAll (" %sDeleted favorite %s" , MESSAGE_HEADER , deletefavorite.name .c_str ());
1011- favorites.updated = true ;
1012- }
1013- deletefavorite.requested = false ;
1014- }
1015-
1016- if (favorites.updated ) {
1017- String s;
1018- ws.textAll (favoritesToString (s));
1019- ESP_LOGD (TAG , " Favorites and clients are updated." );
1020- favorites.updated = false ;
1021- }
1022994}
1023995
1024996void loop () {
0 commit comments