Merge pull request #44 from jpirnay/chore-mutex
chore: Add a couple of mutex locks
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
void BootActivity::onEnter() {
|
void BootActivity::onEnter() {
|
||||||
Activity::onEnter();
|
Activity::onEnter();
|
||||||
|
RenderLock lock(*this);
|
||||||
|
|
||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
|||||||
@@ -98,7 +98,10 @@ void BookInfoActivity::loadData() {
|
|||||||
|
|
||||||
void BookInfoActivity::onEnter() {
|
void BookInfoActivity::onEnter() {
|
||||||
Activity::onEnter();
|
Activity::onEnter();
|
||||||
renderLoading();
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
renderLoading();
|
||||||
|
}
|
||||||
loadData();
|
loadData();
|
||||||
requestUpdate(true);
|
requestUpdate(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,11 +131,9 @@ void HomeActivity::loadRecentBooks(int maxBooks) {
|
|||||||
|
|
||||||
void HomeActivity::loadRecentCovers(int coverHeight) {
|
void HomeActivity::loadRecentCovers(int coverHeight) {
|
||||||
recentsLoading = true;
|
recentsLoading = true;
|
||||||
bool showingLoading = false;
|
|
||||||
Rect popupRect;
|
|
||||||
|
|
||||||
int progress = 0;
|
for (; nextRecentCoverIndex < recentBooks.size(); nextRecentCoverIndex++) {
|
||||||
for (RecentBook& book : recentBooks) {
|
RecentBook& book = recentBooks[nextRecentCoverIndex];
|
||||||
if (!book.coverBmpPath.empty()) {
|
if (!book.coverBmpPath.empty()) {
|
||||||
std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight);
|
std::string coverPath = UITheme::getCoverThumbPath(book.coverBmpPath, coverHeight);
|
||||||
if (!Storage.exists(coverPath.c_str())) {
|
if (!Storage.exists(coverPath.c_str())) {
|
||||||
@@ -146,40 +144,35 @@ void HomeActivity::loadRecentCovers(int coverHeight) {
|
|||||||
epub.load(false, true);
|
epub.load(false, true);
|
||||||
|
|
||||||
// Try to generate thumbnail image for Continue Reading card
|
// Try to generate thumbnail image for Continue Reading card
|
||||||
if (!showingLoading) {
|
|
||||||
showingLoading = true;
|
|
||||||
popupRect = GUI.drawPopup(renderer, tr(STR_LOADING_POPUP));
|
|
||||||
}
|
|
||||||
GUI.fillPopupProgress(renderer, popupRect, 10 + progress * (90 / recentBooks.size()));
|
|
||||||
bool success = epub.generateThumbBmp(coverHeight);
|
bool success = epub.generateThumbBmp(coverHeight);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
RECENT_BOOKS.updateBook(book.path, book.title, book.author, book.series, "");
|
RECENT_BOOKS.updateBook(book.path, book.title, book.author, book.series, "");
|
||||||
book.coverBmpPath = "";
|
book.coverBmpPath = "";
|
||||||
}
|
}
|
||||||
coverRendered = false;
|
coverRendered = false;
|
||||||
|
nextRecentCoverIndex++;
|
||||||
|
recentsLoading = false;
|
||||||
requestUpdate();
|
requestUpdate();
|
||||||
|
return;
|
||||||
} else if (FsHelpers::hasXtcExtension(book.path)) {
|
} else if (FsHelpers::hasXtcExtension(book.path)) {
|
||||||
// Handle XTC file
|
// Handle XTC file
|
||||||
Xtc xtc(book.path, "/.crosspoint");
|
Xtc xtc(book.path, "/.crosspoint");
|
||||||
if (xtc.load()) {
|
if (xtc.load()) {
|
||||||
// Try to generate thumbnail image for Continue Reading card
|
// Try to generate thumbnail image for Continue Reading card
|
||||||
if (!showingLoading) {
|
|
||||||
showingLoading = true;
|
|
||||||
popupRect = GUI.drawPopup(renderer, tr(STR_LOADING_POPUP));
|
|
||||||
}
|
|
||||||
GUI.fillPopupProgress(renderer, popupRect, 10 + progress * (90 / recentBooks.size()));
|
|
||||||
bool success = xtc.generateThumbBmp(coverHeight);
|
bool success = xtc.generateThumbBmp(coverHeight);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
RECENT_BOOKS.updateBook(book.path, book.title, book.author, book.series, "");
|
RECENT_BOOKS.updateBook(book.path, book.title, book.author, book.series, "");
|
||||||
book.coverBmpPath = "";
|
book.coverBmpPath = "";
|
||||||
}
|
}
|
||||||
coverRendered = false;
|
coverRendered = false;
|
||||||
|
nextRecentCoverIndex++;
|
||||||
|
recentsLoading = false;
|
||||||
requestUpdate();
|
requestUpdate();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progress++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
recentsLoaded = true;
|
recentsLoaded = true;
|
||||||
@@ -193,9 +186,18 @@ void HomeActivity::onEnter() {
|
|||||||
hasOpdsUrl = strlen(SETTINGS.opdsServerUrl) > 0;
|
hasOpdsUrl = strlen(SETTINGS.opdsServerUrl) > 0;
|
||||||
|
|
||||||
selectorIndex = 0;
|
selectorIndex = 0;
|
||||||
|
recentsLoading = false;
|
||||||
|
recentsLoaded = false;
|
||||||
|
firstRenderDone = false;
|
||||||
|
nextRecentCoverIndex = 0;
|
||||||
|
coverRendered = false;
|
||||||
|
freeCoverBuffer();
|
||||||
|
|
||||||
const auto& metrics = UITheme::getInstance().getMetrics();
|
const auto& metrics = UITheme::getInstance().getMetrics();
|
||||||
loadRecentBooks(metrics.homeRecentBooksCount);
|
loadRecentBooks(metrics.homeRecentBooksCount);
|
||||||
|
if (recentBooks.empty()) {
|
||||||
|
recentsLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger first update
|
// Trigger first update
|
||||||
requestUpdate();
|
requestUpdate();
|
||||||
@@ -251,6 +253,15 @@ void HomeActivity::freeCoverBuffer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HomeActivity::loop() {
|
void HomeActivity::loop() {
|
||||||
|
if (firstRenderDone && !recentsLoaded && !recentsLoading) {
|
||||||
|
const auto& metrics = UITheme::getInstance().getMetrics();
|
||||||
|
const Rect contentRect = UITheme::getContentRect(renderer, true, false);
|
||||||
|
const int menuItemCount = hasOpdsUrl ? 6 : 5;
|
||||||
|
const HomeScreenLayout layout = computeHomeScreenLayout(metrics, contentRect.height, menuItemCount);
|
||||||
|
loadRecentCovers(getHomeCoverRenderHeight(layout));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const int menuCount = getMenuItemCount();
|
const int menuCount = getMenuItemCount();
|
||||||
|
|
||||||
buttonNavigator.onNext([this, menuCount] {
|
buttonNavigator.onNext([this, menuCount] {
|
||||||
@@ -336,9 +347,6 @@ void HomeActivity::render(RenderLock&&) {
|
|||||||
if (!firstRenderDone) {
|
if (!firstRenderDone) {
|
||||||
firstRenderDone = true;
|
firstRenderDone = true;
|
||||||
requestUpdate();
|
requestUpdate();
|
||||||
} else if (!recentsLoaded && !recentsLoading) {
|
|
||||||
recentsLoading = true;
|
|
||||||
loadRecentCovers(getHomeCoverRenderHeight(layout));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <cstddef>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ class HomeActivity final : public Activity {
|
|||||||
bool hasOpdsUrl = false;
|
bool hasOpdsUrl = false;
|
||||||
bool coverRendered = false; // Track if cover has been rendered once
|
bool coverRendered = false; // Track if cover has been rendered once
|
||||||
bool coverBufferStored = false; // Track if cover buffer is stored
|
bool coverBufferStored = false; // Track if cover buffer is stored
|
||||||
|
size_t nextRecentCoverIndex = 0;
|
||||||
uint8_t* coverBuffer = nullptr; // HomeActivity's own buffer for cover image
|
uint8_t* coverBuffer = nullptr; // HomeActivity's own buffer for cover image
|
||||||
std::vector<RecentBook> recentBooks;
|
std::vector<RecentBook> recentBooks;
|
||||||
void onSelectBook(const std::string& path);
|
void onSelectBook(const std::string& path);
|
||||||
|
|||||||
@@ -58,7 +58,10 @@ void EpubReaderActivity::onEnter() {
|
|||||||
|
|
||||||
// Configure screen orientation based on settings
|
// Configure screen orientation based on settings
|
||||||
// NOTE: This affects layout math and must be applied before any render calls.
|
// NOTE: This affects layout math and must be applied before any render calls.
|
||||||
ReaderUtils::applyOrientation(renderer, SETTINGS.orientation);
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
ReaderUtils::applyOrientation(renderer, SETTINGS.orientation);
|
||||||
|
}
|
||||||
|
|
||||||
epub->setupCacheDir();
|
epub->setupCacheDir();
|
||||||
|
|
||||||
|
|||||||
@@ -125,9 +125,12 @@ void ReaderActivity::onEnter() {
|
|||||||
if (isImageFile(initialBookPath)) {
|
if (isImageFile(initialBookPath)) {
|
||||||
onGoToBmpViewer(initialBookPath);
|
onGoToBmpViewer(initialBookPath);
|
||||||
} else if (isXtcFile(initialBookPath)) {
|
} else if (isXtcFile(initialBookPath)) {
|
||||||
renderer.clearScreen();
|
{
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, 300, tr(STR_LOADING), true, EpdFontFamily::BOLD);
|
RenderLock lock(*this);
|
||||||
renderer.displayBuffer();
|
renderer.clearScreen();
|
||||||
|
renderer.drawCenteredText(UI_12_FONT_ID, 300, tr(STR_LOADING), true, EpdFontFamily::BOLD);
|
||||||
|
renderer.displayBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
auto xtc = loadXtc(initialBookPath);
|
auto xtc = loadXtc(initialBookPath);
|
||||||
if (!xtc) {
|
if (!xtc) {
|
||||||
|
|||||||
@@ -92,7 +92,10 @@ void TxtReaderActivity::onEnter() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReaderUtils::applyOrientation(renderer, SETTINGS.orientation);
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
ReaderUtils::applyOrientation(renderer, SETTINGS.orientation);
|
||||||
|
}
|
||||||
|
|
||||||
txt->setupCacheDir();
|
txt->setupCacheDir();
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ void BmpViewerActivity::onExit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BmpViewerActivity::renderBmpImage(const bool showControls) {
|
bool BmpViewerActivity::renderBmpImage(const bool showControls) {
|
||||||
|
RenderLock lock(*this);
|
||||||
FsFile file;
|
FsFile file;
|
||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
@@ -192,6 +193,7 @@ bool BmpViewerActivity::renderBmpImage(const bool showControls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BmpViewerActivity::renderDecodedImage(const bool showControls) {
|
bool BmpViewerActivity::renderDecodedImage(const bool showControls) {
|
||||||
|
RenderLock lock(*this);
|
||||||
const auto pageWidth = renderer.getScreenWidth();
|
const auto pageWidth = renderer.getScreenWidth();
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
Rect popupRect = GUI.drawPopup(renderer, tr(STR_LOADING_POPUP));
|
Rect popupRect = GUI.drawPopup(renderer, tr(STR_LOADING_POPUP));
|
||||||
@@ -291,8 +293,11 @@ void BmpViewerActivity::toggleDisplayMode() {
|
|||||||
grayscaleDisplay = !grayscaleDisplay;
|
grayscaleDisplay = !grayscaleDisplay;
|
||||||
// Switching between 1-bit BW and 4-level grayscale requires a full refresh to clear
|
// Switching between 1-bit BW and 4-level grayscale requires a full refresh to clear
|
||||||
// ghosting from the previous mode — a half refresh leaves visible residue.
|
// ghosting from the previous mode — a half refresh leaves visible residue.
|
||||||
renderer.clearScreen();
|
{
|
||||||
renderer.displayBuffer(HalDisplay::FULL_REFRESH);
|
RenderLock lock(*this);
|
||||||
|
renderer.clearScreen();
|
||||||
|
renderer.displayBuffer(HalDisplay::FULL_REFRESH);
|
||||||
|
}
|
||||||
if (!renderCurrentImage()) {
|
if (!renderCurrentImage()) {
|
||||||
renderError(tr(STR_COULD_NOT_RENDER_IMAGE));
|
renderError(tr(STR_COULD_NOT_RENDER_IMAGE));
|
||||||
}
|
}
|
||||||
@@ -335,6 +340,7 @@ void BmpViewerActivity::saveDitherSettingsIfNeeded() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void BmpViewerActivity::renderError(const char* message) {
|
void BmpViewerActivity::renderError(const char* message) {
|
||||||
|
RenderLock lock(*this);
|
||||||
const auto pageHeight = renderer.getScreenHeight();
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, message);
|
renderer.drawCenteredText(UI_10_FONT_ID, pageHeight / 2, message);
|
||||||
@@ -365,8 +371,11 @@ void BmpViewerActivity::setAsSleepScreen() {
|
|||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
LOG_ERR("BMP", "Failed to set %s as sleep screen", filePath.c_str());
|
LOG_ERR("BMP", "Failed to set %s as sleep screen", filePath.c_str());
|
||||||
GUI.drawPopup(renderer, tr(STR_FAILED_TO_SET_SLEEP_SCREEN));
|
{
|
||||||
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
RenderLock lock(*this);
|
||||||
|
GUI.drawPopup(renderer, tr(STR_FAILED_TO_SET_SLEEP_SCREEN));
|
||||||
|
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,8 +383,11 @@ void BmpViewerActivity::setAsSleepScreen() {
|
|||||||
SETTINGS.saveToFile();
|
SETTINGS.saveToFile();
|
||||||
LOG_INF("BMP", "Set %s as sleep screen", filePath.c_str());
|
LOG_INF("BMP", "Set %s as sleep screen", filePath.c_str());
|
||||||
|
|
||||||
GUI.drawPopup(renderer, tr(STR_SLEEP_SCREEN_SET));
|
{
|
||||||
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
RenderLock lock(*this);
|
||||||
|
GUI.drawPopup(renderer, tr(STR_SLEEP_SCREEN_SET));
|
||||||
|
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BmpViewerActivity::loop() {
|
void BmpViewerActivity::loop() {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
void FullScreenMessageActivity::onEnter() {
|
void FullScreenMessageActivity::onEnter() {
|
||||||
Activity::onEnter();
|
Activity::onEnter();
|
||||||
|
RenderLock lock(*this);
|
||||||
|
|
||||||
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||||
const auto top = (renderer.getScreenHeight() - height) / 2;
|
const auto top = (renderer.getScreenHeight() - height) / 2;
|
||||||
|
|||||||
@@ -202,7 +202,10 @@ void WeatherActivity::onEnter() {
|
|||||||
Activity::onEnter();
|
Activity::onEnter();
|
||||||
|
|
||||||
// Force landscape orientation for weather display
|
// Force landscape orientation for weather display
|
||||||
renderer.setOrientation(GfxRenderer::Orientation::LandscapeClockwise);
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
renderer.setOrientation(GfxRenderer::Orientation::LandscapeClockwise);
|
||||||
|
}
|
||||||
|
|
||||||
state = State::LOADING_CACHE;
|
state = State::LOADING_CACHE;
|
||||||
errorMessage.clear();
|
errorMessage.clear();
|
||||||
@@ -283,7 +286,10 @@ void WeatherActivity::launchWifiSelection() {
|
|||||||
|
|
||||||
void WeatherActivity::onWifiSelectionComplete(bool connected) {
|
void WeatherActivity::onWifiSelectionComplete(bool connected) {
|
||||||
// Re-apply landscape after returning from WiFi selection (which uses portrait)
|
// Re-apply landscape after returning from WiFi selection (which uses portrait)
|
||||||
renderer.setOrientation(GfxRenderer::Orientation::LandscapeClockwise);
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
renderer.setOrientation(GfxRenderer::Orientation::LandscapeClockwise);
|
||||||
|
}
|
||||||
LOG_DBG("WEA", "onWifiSelectionComplete connected=%d wifiStatus=%d", connected ? 1 : 0, (int)WiFi.status());
|
LOG_DBG("WEA", "onWifiSelectionComplete connected=%d wifiStatus=%d", connected ? 1 : 0, (int)WiFi.status());
|
||||||
|
|
||||||
if (connected) {
|
if (connected) {
|
||||||
@@ -325,10 +331,16 @@ void WeatherActivity::fetchWeather() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WeatherActivity::openSettingsActivity() {
|
void WeatherActivity::openSettingsActivity() {
|
||||||
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
renderer.setOrientation(GfxRenderer::Orientation::Portrait);
|
||||||
|
}
|
||||||
startActivityForResult(std::make_unique<WeatherSettingsActivity>(renderer, mappedInput),
|
startActivityForResult(std::make_unique<WeatherSettingsActivity>(renderer, mappedInput),
|
||||||
[this](const ActivityResult&) {
|
[this](const ActivityResult&) {
|
||||||
renderer.setOrientation(GfxRenderer::Orientation::LandscapeClockwise);
|
{
|
||||||
|
RenderLock lock(*this);
|
||||||
|
renderer.setOrientation(GfxRenderer::Orientation::LandscapeClockwise);
|
||||||
|
}
|
||||||
forceRefresh = true;
|
forceRefresh = true;
|
||||||
loadAndDisplay();
|
loadAndDisplay();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user