modyfikacja PLAYLIST WIDGET - paginacja zamiast przewijania całego ekranu
przetestowane dla:
- v-tom 7.13 (powinno działać z v-tom 7.5-8.2)
- ekranu 480x320 ST7796 (dla ILI9488 też powinno działać)
należy wymienić cały obecny kod PLAYLIST WIDGET na poniższy oraz wprowadzić zmianę w mytheme.h
mytheme.h
#define COLOR_PL_CURRENT 250, 250, 250 // kolor wybranego na playliście streamu
#define COLOR_PL_CURRENT_BG 0, 0, 0 // zerowanie do tła
#define COLOR_PL_CURRENT_FILL 0, 0, 0 // zerowanie do tła
#define COLOR_PLAYLIST_0 165, 165, 165 // kolor pozostałych linii playlisty, następne kolory nieużywane w kodzie
#define COLOR_PLAYLIST_1 165, 165, 165
#define COLOR_PLAYLIST_2 165, 165, 165
#define COLOR_PLAYLIST_3 165, 165, 165
#define COLOR_PLAYLIST_4 165, 165, 165
widgets.cpp
// =================================
// PLAYLIST WIDGET - FINALNA WERSJA
// =================================
#define MAX_PL_PAGE_ITEMS 15
static String _plCache[MAX_PL_PAGE_ITEMS];
static int16_t _plLoadedPage = -1;
static int16_t _plLastGlobalPos = -1;
static uint32_t _plLastDrawTime = 0;
void PlayListWidget::init(ScrollWidget *current) {
Widget::init({0, 0, 0, WA_LEFT}, 0, 0);
#ifndef DSP_LCD
_plItemHeight = playlistConf.widget.textsize * (CHARHEIGHT - 1) + playlistConf.widget.textsize * 4;
_plTtemsCount = (dsp.height() - 2) / _plItemHeight;
if (_plTtemsCount < 1) _plTtemsCount = 1;
if (_plTtemsCount > MAX_PL_PAGE_ITEMS) _plTtemsCount = MAX_PL_PAGE_ITEMS;
uint16_t contentHeight = _plTtemsCount * _plItemHeight;
_plYStart = (dsp.height() - contentHeight) / 2;
#else
_plTtemsCount = PLMITEMS;
_plCurrentPos = 0;
#endif
_plLoadedPage = -1;
_plLastGlobalPos = -1;
_plCurrentPos = 0;
_plLastDrawTime = 0;
}
void _loadPlaylistPage(int pageIndex, int itemsPerPage, int totalItems) {
for (int i = 0; i < MAX_PL_PAGE_ITEMS; i++) _plCache[i] = "";
if (config.playlistLength() == 0) return;
File playlist = config.SDPLFS()->open(REAL_PLAYL, "r");
File index = config.SDPLFS()->open(REAL_INDEX, "r");
if (!playlist || !index) return;
int startIdx = pageIndex * itemsPerPage;
for (int i = 0; i < itemsPerPage; i++) {
int currentGlobalIdx = startIdx + i;
if (currentGlobalIdx >= config.playlistLength()) break;
index.seek(currentGlobalIdx * 4, SeekSet);
uint32_t posAddr;
if (index.readBytes((char *)&posAddr, 4) != 4) break;
playlist.seek(posAddr, SeekSet);
String line = playlist.readStringUntil('\n');
int tabIdx = line.indexOf('\t');
if (tabIdx > 0) line = line.substring(0, tabIdx);
line.trim();
if (config.store.numplaylist && line.length() > 0) {
_plCache[i] = String(currentGlobalIdx + 1) + " " + line;
} else {
_plCache[i] = line;
}
}
playlist.close();
index.close();
}
void PlayListWidget::drawPlaylist(uint16_t currentItem) {
#ifndef DSP_LCD
// Jeśli od ostatniego wywołania minęło > 2000ms to uznajemy, że wracamy z innego ekranu i przerysowujemy cały ekran
bool isLongPause = (millis() - _plLastDrawTime > 2000);
_plLastDrawTime = millis();
int activeIdx = (currentItem > 0) ? (currentItem - 1) : 0;
int itemsPerPage = _plTtemsCount;
int newPage = activeIdx / itemsPerPage;
int newLocalPos = activeIdx % itemsPerPage;
_plCurrentPos = newLocalPos;
bool pageChanged = (newPage != _plLoadedPage);
// WARUNKI PEŁNEGO RYSOWANIA:
// 1. Zmiana strony
// 2. Powrót do playera (V-Tom 2 sekundy / potwierdzenie automatyczne wyboru streamu)
// 3. Pusty cache (start)
if (pageChanged || isLongPause || _plCache[0].length() == 0) {
// Jeśli to tylko powrót do tej samej strony, nie musimy czytać z pamięci (oszczędność czasu)
// Czytamy z pamięci tylko gdy faktycznie zmieniła się strona lub cache jest pusty.
if (pageChanged || _plCache[0].length() == 0) {
_loadPlaylistPage(newPage, itemsPerPage, config.playlistLength());
_plLoadedPage = newPage;
}
// Rysujemy całe tło i listę (to usuwa śmieci po playerze)
dsp.fillRect(0, _plYStart, dsp.width(), itemsPerPage * _plItemHeight, config.theme.background);
for (int i = 0; i < itemsPerPage; i++) {
_printPLitem(i, _plCache[i].c_str());
}
} else {
// SMART REDRAW - Szybka ścieżka dla płynnego przewijania
int oldLocalPos = (_plLastGlobalPos > 0 ? _plLastGlobalPos - 1 : 0) % itemsPerPage;
if (oldLocalPos != newLocalPos && oldLocalPos >= 0 && oldLocalPos < itemsPerPage) {
_printPLitem(oldLocalPos, _plCache[oldLocalPos].c_str());
}
_printPLitem(newLocalPos, _plCache[newLocalPos].c_str());
}
_plLastGlobalPos = currentItem;
#else
dsp.setCursor(0, 0);
dsp.print(F("CH: "));
dsp.print(currentItem);
dsp.print(F(" "));
#endif
}
void PlayListWidget::_printPLitem(uint8_t pos, const char *item) {
#ifndef DSP_LCD
if (pos >= _plTtemsCount) return;
int16_t yPos = _plYStart + pos * _plItemHeight;
bool isSelected = (pos == _plCurrentPos);
uint16_t fgColor = isSelected ? config.theme.plcurrent : config.theme.playlist[0];
uint16_t bgColor = config.theme.background;
// dsp.fillRect(0, yPos, dsp.width(), _plItemHeight - 1, bgColor); // zbędna linia (poprawka)
if (item && item[0] != '\0') {
dsp.setTextColor(fgColor, bgColor);
dsp.setTextSize(playlistConf.widget.textsize);
dsp.setCursor(TFT_FRAMEWDT, yPos + 4);
dsp.print(utf8To(item, true));
}
#endif
}