Skip to content

Commit 87468a9

Browse files
Add config info to Diagnostics view; switch SpotifyArduino to use lateInit() with a global instance
1 parent 364957b commit 87468a9

File tree

9 files changed

+92
-24
lines changed

9 files changed

+92
-24
lines changed

platformio.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
platform = espressif32@~6.10.0
1313
; esp-wrover-kit is 4MB ESP32-WROVER-B compatible.
1414
board = esp-wrover-kit
15-
; custom_esp-wrover-kit to enable 8MB PSRAM and a larger heap.
15+
; custom_esp-wrover-kit to enable 8MB PSRAM
1616
;board = custom_esp-wrover-kit
1717
framework = arduino
1818
monitor_speed = 115200

src/SpotifyArtMgr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,20 @@ void SpotifyArtMgr::determineCacheSize()
694694
}
695695
}
696696

697+
/*
698+
** ===================================================================
699+
** getMaxCacheSize()
700+
** Returns the current maximum cache size used for album art.
701+
**
702+
** Returns:
703+
** size_t - The maximum number of cached album art entries.
704+
** ===================================================================
705+
*/
706+
size_t SpotifyArtMgr::getMaxCacheSize()
707+
{
708+
return _maxCacheSize;
709+
}
710+
697711
/*
698712
** ===================================================================
699713
** loadCacheIndex()

src/SpotifyArtMgr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class SpotifyArtMgr
7676
static SpotifyArtMgr* getInstance();
7777

7878
void setMaxCacheSize(size_t maxSize);
79+
size_t getMaxCacheSize();
7980
void saveCacheIndex();
8081
bool isCacheDirty();
8182

src/SpotifyPlayer.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,8 @@ void SpotifyPlayer::initialize(QueueHandle_t *pScuiQueue)
8383
_spotifyClientId = Vault::getInstance().getSpotifyClientID();
8484
_spotifyClientSecret = Vault::getInstance().getSpotifyClientSecret();
8585

86-
_pSpotify = new SpotifyArduino(
87-
client,
88-
_spotifyClientId.c_str(),
89-
_spotifyClientSecret.c_str()
90-
);
86+
spotify.lateInit(_spotifyClientId.c_str(), _spotifyClientSecret.c_str(), _spotifyRefreshToken.c_str());
87+
9188
// client is defined in ThingPulse/spotify.h
9289
client.setCACert(spotify_server_cert);
9390

@@ -168,7 +165,7 @@ bool SpotifyPlayer::requestRefreshToken()
168165
spLogI(LOGTAG_PLAYER, "Requesting Spotify refresh token through the browser via auth code.");
169166

170167
String spotifyAuthCode = fetchSpotifyAuthCode();
171-
_spotifyRefreshToken = _pSpotify->requestAccessTokens(spotifyAuthCode.c_str(), SPOTIFY_REDIRECT_URI);
168+
_spotifyRefreshToken = spotify.requestAccessTokens(spotifyAuthCode.c_str(), SPOTIFY_REDIRECT_URI);
172169
SCFileIO::getInstance().saveFsString(SPOTIFY_REFRESH_TOKEN_FILE_NAME, _spotifyRefreshToken);
173170

174171
return true;
@@ -196,8 +193,8 @@ void SpotifyPlayer::login()
196193
// - keeps track of the refresh token and its TTL internally
197194
// - automatically renews the actual access token using the refresh token
198195
// -> see SpotifyArduino.h#autoTokenRefresh and SpotifyArduino::checkAndRefreshAccessToken() (called before every API function)
199-
_pSpotify->setRefreshToken(_spotifyRefreshToken.c_str());
200-
_pSpotify->refreshAccessToken();
196+
spotify.setRefreshToken(_spotifyRefreshToken.c_str());
197+
spotify.refreshAccessToken();
201198
spLogI(LOGTAG_PLAYER, "Authentication against Spotify done. Refresh token: %s", _spotifyRefreshToken.c_str());
202199
}
203200

@@ -251,7 +248,7 @@ void SpotifyPlayer::nextSong()
251248
static_cast<int>(TFTColor::SC_NetworkInProgress));
252249
if (xSemaphoreTake(_xSemaphoreNetwork, portMAX_DELAY))
253250
{
254-
if (_pSpotify->nextTrack())
251+
if (spotify.nextTrack())
255252
{
256253
postScuiMessage(SCUIMessageType::UM_STATUS_BOX,
257254
"",
@@ -291,7 +288,7 @@ void SpotifyPlayer::previousSong()
291288

292289
if (xSemaphoreTake(_xSemaphoreNetwork, portMAX_DELAY))
293290
{
294-
if (_pSpotify->previousTrack())
291+
if (spotify.previousTrack())
295292
{
296293
postScuiMessage(SCUIMessageType::UM_STATUS_BOX,
297294
"",
@@ -333,7 +330,7 @@ void SpotifyPlayer::pauseSong()
333330
postScuiMessage(SCUIMessageType::UM_STATUS_BOX,
334331
"Making Call",
335332
static_cast<int>(TFTColor::SC_NetworkInProgress));
336-
if (_pSpotify->pause())
333+
if (spotify.pause())
337334
{
338335
postScuiMessage(SCUIMessageType::UM_STATUS_BOX,
339336
"",
@@ -353,7 +350,7 @@ void SpotifyPlayer::pauseSong()
353350
postScuiMessage(SCUIMessageType::UM_STATUS_BOX,
354351
"Making Call",
355352
static_cast<int>(TFTColor::SC_NetworkInProgress));
356-
if (_pSpotify->play())
353+
if (spotify.play())
357354
{
358355
postScuiMessage(SCUIMessageType::UM_STATUS_BOX,
359356
"",
@@ -399,7 +396,7 @@ void SpotifyPlayer::refreshCurrentTrack()
399396
{
400397
spLogI(LOGTAG_MULTITASK, "Invoking spotify.getCurrentlyPlaying(...)");
401398
Monitor::start(MONITOR_ID_SPOTIFY_GET_CURRENTLY_PLAYING, LOGTAG_METRICS, "spotify.getCurrentlyPlaying(...)");
402-
status = _pSpotify->getCurrentlyPlaying(SpotifyPlayer::getCurrentlyPlayingCallback, SP_SPOTIFY_MARKET);
399+
status = spotify.getCurrentlyPlaying(SpotifyPlayer::getCurrentlyPlayingCallback, SP_SPOTIFY_MARKET);
403400
Monitor::stop(MONITOR_ID_SPOTIFY_GET_CURRENTLY_PLAYING);
404401
xSemaphoreGive(_xSemaphoreNetwork);
405402
}

src/SpotifyPlayer.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@
2020
#include "DisplayUI.h"
2121
#include "PlayingMetadata.h"
2222
#include "scui.h"
23-
24-
// Forward declaration to avoid including full spotify.h in the header
25-
class SpotifyArduino;
2623
class SpotifyPlayer {
2724
public:
2825
// Public method to access the singleton instance
@@ -53,7 +50,6 @@ class SpotifyPlayer {
5350
private:
5451
// Member variables
5552
String _spotifyRefreshToken = "";
56-
// DisplayUI *_pUI;
5753
QueueHandle_t *_pScuiQueue;
5854
String _currentTrackUri = ""; // Tracks the currently playing song
5955
bool _isPlaying = false;
@@ -66,7 +62,6 @@ class SpotifyPlayer {
6662
SemaphoreHandle_t _xSemaphoreNetwork = xSemaphoreCreateMutex();
6763
SemaphoreHandle_t _xSemaphoreDataCopy = xSemaphoreCreateMutex();
6864
TaskHandle_t _refreshTaskHandle;
69-
SpotifyArduino *_pSpotify = nullptr;
7065
String _spotifyClientId;
7166
String _spotifyClientSecret;
7267

src/ThingPulse/spotify.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <ArduinoJson.h>
2323
#include <ESPmDNS.h>
2424
#include <SpotifyArduino.h>
25-
// #include <SpotifyArduinoCert.h>
2625
#include <WebServer.h>
2726
#include <WiFi.h>
2827
#include <WiFiClient.h>
@@ -53,6 +52,13 @@ String scope = "user-read-playback-state%20user-modify-playback-state";
5352
WebServer server(80);
5453
WiFiClientSecure client;
5554

55+
// Note: SpotifyArduino does not initialize its _refreshToken pointer.
56+
// When declared as a global, this works because globals are zero-initialized by default,
57+
// making _refreshToken safely nullptr. If the instance is created dynamically or locally,
58+
// this assumption can lead to heap corruption when delete is called on an uninitialized
59+
// _refreshToken in setRefreshToken().
60+
SpotifyArduino spotify(client);
61+
5662
const char *webpageTemplate =
5763
R"(
5864
<!DOCTYPE html>
@@ -130,8 +136,6 @@ String fetchSpotifyAuthCode() {
130136
log_i("Open browser at http://%s.local", SPOTIFY_ESPOTIFIER_NODE_NAME);
131137
}
132138

133-
//printRootWebpage();
134-
135139
server.on("/", handleRoot);
136140
server.on("/callback/", handleCallback);
137141
server.on("/favicon.ico", handleFavicon);

src/UIViews/DiagnosticsView.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "settings.h"
2525
#include "Renderers/BackButtonRenderer.h"
2626
#include "esp_heap_caps.h"
27+
#include "Vault.h"
28+
#include "SpotifyArtMgr.h"
2729

2830
/*
2931
** ===================================================================
@@ -119,8 +121,15 @@ void DiagnosticsView::clearAndPaintScreen(PlayingMetadata playing)
119121
// **** Track Progress Header *****=
120122
_pUI->lDrawString("progressMs / durationMs :: lastRefreshMs (Pct)", 10, rowToY(4), fontSize, TFTColor::DarkGreen, TFTColor::Black,"");
121123

122-
// **** Compile / Version Information *****
123-
std::string versionStr = std::string("Version: ") + VERSION;
124+
// **** Compile / Version / Config Information *****
125+
char buffer[40];
126+
snprintf(buffer, sizeof(buffer), "Config: %c %c %d",
127+
toString(Vault::getInstance().getCredentialSource())[0],
128+
toString(Vault::getInstance().getPrivacyLevel())[0],
129+
SpotifyArtMgr::getInstance()->getMaxCacheSize());
130+
std::string configInfo = std::string(buffer);
131+
132+
std::string versionStr = std::string("Version: ") + VERSION + " - " + configInfo;
124133
_pUI->lDrawString(versionStr.c_str(), 90, rowToY(12), fontSize, TFTColor::DarkGrey, TFTColor::Black,"#### ################## ####");
125134
versionStr = std::string("Compile: ") + COMPILE_TIME;
126135
_pUI->lDrawString(versionStr.c_str(), 90, rowToY(13), fontSize, TFTColor::DarkGrey, TFTColor::Black,"#### ################## ####");

src/Vault.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,25 @@ const char* toString(VaultPrivacyLevel level)
5757
}
5858
}
5959

60+
/*
61+
** ===================================================================
62+
** toString(CredentialSource)
63+
**
64+
** Converts a CredentialSource enum value to its corresponding
65+
** string representation for logging, diagnostics, and debugging.
66+
** ===================================================================
67+
*/
68+
const char* toString(CredentialSource source)
69+
{
70+
switch (source)
71+
{
72+
case CredentialSource::Hardcoded: return "Hardcoded";
73+
case CredentialSource::INIFile: return "INIFile";
74+
default: return "Unknown";
75+
}
76+
}
77+
78+
6079
/*
6180
** ===================================================================
6281
** getInstance()
@@ -265,6 +284,23 @@ VaultPrivacyLevel Vault::getPrivacyLevel()
265284
return _privacyLevel;
266285
}
267286

287+
/*
288+
** ===================================================================
289+
** getCredentialSource()
290+
**
291+
** Returns the current source of credentials in use.
292+
** If _useHardcodedValues is true, credentials are coming from
293+
** settings.h; otherwise, they are sourced from user.ini.
294+
**
295+
** Returns:
296+
** CredentialSource enum value indicating the source.
297+
** ===================================================================
298+
*/
299+
CredentialSource Vault::getCredentialSource()
300+
{
301+
return _useHardcodedValues ? CredentialSource::Hardcoded : CredentialSource::INIFile;
302+
}
303+
268304
/*
269305
** ===================================================================
270306
** getSSID()

src/Vault.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ enum class VaultPrivacyLevel
5151
Better // Use AES-encrypted credentials; tied to device MAC address, non-reusable
5252
};
5353

54+
// Defines credential source
55+
enum class CredentialSource
56+
{
57+
Hardcoded, // Plaintext hardcoded values
58+
INIFile, // Loaded values from the ini file
59+
};
60+
61+
const char* toString(VaultPrivacyLevel level);
62+
const char* toString(CredentialSource source);
63+
5464
// Vault definition
5565
class Vault
5666
{
@@ -59,6 +69,8 @@ class Vault
5969

6070
void setPrivacyLevel(VaultPrivacyLevel level);
6171
VaultPrivacyLevel getPrivacyLevel();
72+
CredentialSource getCredentialSource();
73+
6274
void initialize();
6375
void eraseEncryptedCredentials();
6476

0 commit comments

Comments
 (0)