From a57ca5edc1ad0a2101e368569ea4f7242097fd46 Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Wed, 17 Aug 2022 09:17:04 +0200 Subject: [PATCH] made ROM info delay adaptive some cleanup of the new JPG reading code --- src/common/JPGLibrary.cxx | 14 +++--- src/common/JPGLibrary.hxx | 9 ++-- src/common/PNGLibrary.cxx | 69 ++++++++++++++--------------- src/common/PNGLibrary.hxx | 33 +++++++------- src/gui/LauncherDialog.cxx | 33 ++++++++++---- src/gui/RomImageWidget.cxx | 91 ++++++++++++++++++++------------------ src/gui/RomImageWidget.hxx | 17 +++++-- src/gui/RomInfoWidget.cxx | 11 ++--- src/gui/RomInfoWidget.hxx | 2 +- 9 files changed, 153 insertions(+), 126 deletions(-) diff --git a/src/common/JPGLibrary.cxx b/src/common/JPGLibrary.cxx index 80c346da8..eb8cadc03 100644 --- a/src/common/JPGLibrary.cxx +++ b/src/common/JPGLibrary.cxx @@ -33,7 +33,7 @@ JPGLibrary::JPGLibrary(OSystem& osystem) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void JPGLibrary::loadImage(const string& filename, FBSurface& surface, - VariantList& comments) + VariantList& metaData) { const auto loadImageERROR = [&](const char* s) { if(s) @@ -63,8 +63,8 @@ void JPGLibrary::loadImage(const string& filename, FBSurface& surface, myReadInfo.height = njGetHeight(); myReadInfo.pitch = myReadInfo.width * 3; - // Read the comments we got TODO - //readComments(png_ptr, info_ptr, comments); + // TODO: Read the meta data we got + //readMetaData(png_ptr, info_ptr, metaData); // Load image into the surface, setting the correct dimensions loadImagetoSurface(surface); @@ -103,8 +103,8 @@ void JPGLibrary::loadImagetoSurface(FBSurface& surface) } //// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//void JPGLibrary::readComments(const png_structp png_ptr, png_infop info_ptr, -// VariantList& comments) +//void JPGLibrary::readMetaData(const png_structp png_ptr, png_infop info_ptr, +// VariantList& metaData) //{ // png_textp text_ptr; // int numComments = 0; @@ -112,10 +112,10 @@ void JPGLibrary::loadImagetoSurface(FBSurface& surface) // // TODO: currently works only if comments are *before* the image data // png_get_text(png_ptr, info_ptr, &text_ptr, &numComments); // -// comments.clear(); +// metaData.clear(); // for(int i = 0; i < numComments; ++i) // { -// VarList::push_back(comments, text_ptr[i].key, text_ptr[i].text); +// VarList::push_back(metaData, text_ptr[i].key, text_ptr[i].text); // } //} diff --git a/src/common/JPGLibrary.hxx b/src/common/JPGLibrary.hxx index 1d98c4ae4..a0af35817 100644 --- a/src/common/JPGLibrary.hxx +++ b/src/common/JPGLibrary.hxx @@ -40,12 +40,13 @@ class JPGLibrary @param filename The filename to load the JPG image @param surface The FBSurface into which to place the JPG data + @param metaData The meta data of the JPG image @post On success, the FBSurface containing image data, otherwise a runtime_error is thrown containing a more detailed error message. */ - void loadImage(const string& filename, FBSurface& surface, VariantList& comments); + void loadImage(const string& filename, FBSurface& surface, VariantList& metaData); private: // Global OSystem object @@ -70,10 +71,10 @@ class JPGLibrary void loadImagetoSurface(FBSurface& surface); ///** - // Read EXIF metadata chunks from the image. + // Read EXIF meta data chunks from the image. //*/ - //void readComments(const png_structp png_ptr, png_infop info_ptr, - // VariantList& comments); + //void readmetaData(const png_structp png_ptr, png_infop info_ptr, + // VariantList& metaData); private: // Following constructors and assignment operators not supported diff --git a/src/common/PNGLibrary.cxx b/src/common/PNGLibrary.cxx index 304f74bbc..6a56d2d11 100644 --- a/src/common/PNGLibrary.cxx +++ b/src/common/PNGLibrary.cxx @@ -33,7 +33,7 @@ PNGLibrary::PNGLibrary(OSystem& osystem) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantList& comments) +void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantList& metaData) { png_structp png_ptr{nullptr}; png_infop info_ptr{nullptr}; @@ -109,8 +109,8 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi // We're finished reading png_read_end(png_ptr, info_ptr); - // Read the comments we got - readComments(png_ptr, info_ptr, comments); + // Read the meta data we got + readMetaData(png_ptr, info_ptr, metaData); // Load image into the surface, setting the correct dimensions loadImagetoSurface(surface); @@ -121,7 +121,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PNGLibrary::saveImage(const string& filename, const VariantList& comments) +void PNGLibrary::saveImage(const string& filename, const VariantList& metaData) { std::ofstream out(filename, std::ios_base::binary); if(!out.is_open()) @@ -147,12 +147,12 @@ void PNGLibrary::saveImage(const string& filename, const VariantList& comments) rows[k] = buffer.data() + k*width*4; // And save the image - saveImageToDisk(out, rows, width, height, comments); + saveImageToDisk(out, rows, width, height, metaData); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PNGLibrary::saveImage(const string& filename, const FBSurface& surface, - const Common::Rect& rect, const VariantList& comments) + const Common::Rect& rect, const VariantList& metaData) { std::ofstream out(filename, std::ios_base::binary); if(!out.is_open()) @@ -176,12 +176,12 @@ void PNGLibrary::saveImage(const string& filename, const FBSurface& surface, rows[k] = buffer.data() + k*width*4; // And save the image - saveImageToDisk(out, rows, width, height, comments); + saveImageToDisk(out, rows, width, height, metaData); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PNGLibrary::saveImageToDisk(std::ofstream& out, const vector& rows, - png_uint_32 width, png_uint_32 height, const VariantList& comments) + png_uint_32 width, png_uint_32 height, const VariantList& metaData) { png_structp png_ptr = nullptr; png_infop info_ptr = nullptr; @@ -212,8 +212,8 @@ void PNGLibrary::saveImageToDisk(std::ofstream& out, const vector& ro PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - // Write comments - writeComments(png_ptr, info_ptr, comments); + // Write meta data + writeMetaData(png_ptr, info_ptr, metaData); // Write the file header information. REQUIRED png_write_info(png_ptr, info_ptr); @@ -331,18 +331,18 @@ void PNGLibrary::takeSnapshot(uInt32 number) filename = sspath + ".png"; // Some text fields to add to the PNG snapshot - VariantList comments; + VariantList metaData; ostringstream version; - VarList::push_back(comments, "Title", "Snapshot"); + VarList::push_back(metaData, "Title", "Snapshot"); version << "Stella " << STELLA_VERSION << " (Build " << STELLA_BUILD << ") [" << BSPF::ARCH << "]"; - VarList::push_back(comments, "Software", version.str()); + VarList::push_back(metaData, "Software", version.str()); const string& name = (myOSystem.settings().getString("snapname") == "int") ? myOSystem.console().properties().get(PropType::Cart_Name) : myOSystem.romFile().getName(); - VarList::push_back(comments, "ROM Name", name); - VarList::push_back(comments, "ROM MD5", myOSystem.console().properties().get(PropType::Cart_MD5)); - VarList::push_back(comments, "TV Effects", myOSystem.frameBuffer().tiaSurface().effectsInfo()); + VarList::push_back(metaData, "ROM Name", name); + VarList::push_back(metaData, "ROM MD5", myOSystem.console().properties().get(PropType::Cart_MD5)); + VarList::push_back(metaData, "TV Effects", myOSystem.frameBuffer().tiaSurface().effectsInfo()); // Now create a PNG snapshot string message = "Snapshot saved"; @@ -352,7 +352,7 @@ void PNGLibrary::takeSnapshot(uInt32 number) { Common::Rect rect; const FBSurface& surface = myOSystem.frameBuffer().tiaSurface().baseSurface(rect); - myOSystem.png().saveImage(filename, surface, rect, comments); + myOSystem.png().saveImage(filename, surface, rect, metaData); } catch(const runtime_error& e) { @@ -367,7 +367,7 @@ void PNGLibrary::takeSnapshot(uInt32 number) try { - myOSystem.png().saveImage(filename, comments); + myOSystem.png().saveImage(filename, metaData); } catch(const runtime_error& e) { @@ -429,38 +429,37 @@ void PNGLibrary::loadImagetoSurface(FBSurface& surface) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PNGLibrary::writeComments(const png_structp png_ptr, png_infop info_ptr, - const VariantList& comments) +void PNGLibrary::writeMetaData(const png_structp png_ptr, png_infop info_ptr, + const VariantList& metaData) { - const uInt32 numComments = static_cast(comments.size()); - if(numComments == 0) + const uInt32 numMetaData = static_cast(metaData.size()); + if(numMetaData == 0) return; - vector text_ptr(numComments); - for(uInt32 i = 0; i < numComments; ++i) + vector text_ptr(numMetaData); + for(uInt32 i = 0; i < numMetaData; ++i) { - text_ptr[i].key = const_cast(comments[i].first.c_str()); - text_ptr[i].text = const_cast(comments[i].second.toCString()); + text_ptr[i].key = const_cast(metaData[i].first.c_str()); + text_ptr[i].text = const_cast(metaData[i].second.toCString()); text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE; text_ptr[i].text_length = 0; } - png_set_text(png_ptr, info_ptr, text_ptr.data(), numComments); + png_set_text(png_ptr, info_ptr, text_ptr.data(), numMetaData); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PNGLibrary::readComments(const png_structp png_ptr, png_infop info_ptr, - VariantList& comments) +void PNGLibrary::readMetaData(const png_structp png_ptr, png_infop info_ptr, + VariantList& metaData) { png_textp text_ptr; - int numComments = 0; + int numMetaData = 0; - // TODO: currently works only if comments are *before* the image data - png_get_text(png_ptr, info_ptr, &text_ptr, &numComments); + png_get_text(png_ptr, info_ptr, &text_ptr, &numMetaData); - comments.clear(); - for(int i = 0; i < numComments; ++i) + metaData.clear(); + for(int i = 0; i < numMetaData; ++i) { - VarList::push_back(comments, text_ptr[i].key, text_ptr[i].text); + VarList::push_back(metaData, text_ptr[i].key, text_ptr[i].text); } } diff --git a/src/common/PNGLibrary.hxx b/src/common/PNGLibrary.hxx index 4933bcf46..cca961453 100644 --- a/src/common/PNGLibrary.hxx +++ b/src/common/PNGLibrary.hxx @@ -15,7 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#ifdef IMAGE_SUPPORT +#ifdef IMAGE_SUPPORT #ifndef PNGLIBRARY_HXX #define PNGLIBRARY_HXX @@ -43,12 +43,13 @@ class PNGLibrary @param filename The filename to load the PNG image @param surface The FBSurface into which to place the PNG data + @param metaData The meta data of the PNG image @post On success, the FBSurface containing image data, otherwise a runtime_error is thrown containing a more detailed error message. */ - void loadImage(const string& filename, FBSurface& surface, VariantList& comments); + void loadImage(const string& filename, FBSurface& surface, VariantList& metaData); /** Save the current FrameBuffer image to a PNG file. Note that in most @@ -56,14 +57,14 @@ class PNGLibrary *any* mode. @param filename The filename to save the PNG image - @param comments The text comments to add to the PNG image + @param metaData The meta data s to add to the PNG image @post On success, the PNG file has been saved to 'filename', otherwise a runtime_error is thrown containing a more detailed error message. */ void saveImage(const string& filename, - const VariantList& comments = VariantList{}); + const VariantList& metaData = VariantList{}); /** Save the given surface to a PNG file. @@ -71,7 +72,7 @@ class PNGLibrary @param filename The filename to save the PNG image @param surface The surface data for the PNG image @param rect The area of the surface to use - @param comments The text comments to add to the PNG image + @param metaData The meta data to add to the PNG image @post On success, the PNG file has been saved to 'filename', otherwise a runtime_error is thrown containing a @@ -79,7 +80,7 @@ class PNGLibrary */ void saveImage(const string& filename, const FBSurface& surface, const Common::Rect& rect = Common::Rect{}, - const VariantList& comments = VariantList{}); + const VariantList& metaData = VariantList{}); /** Called at regular intervals, and used to determine whether a @@ -155,15 +156,15 @@ class PNGLibrary /** The actual method which saves a PNG image. - @param out The output stream for writing PNG data - @param rows Pointer into PNG RGB data for each row - @param width The width of the PNG image - @param height The height of the PNG image - @param comments The text comments to add to the PNG image + @param out The output stream for writing PNG data + @param rows Pointer into PNG RGB data for each row + @param width The width of the PNG image + @param height The height of the PNG image + @param metaData The meta data to add to the PNG image */ void saveImageToDisk(std::ofstream& out, const vector& rows, png_uint_32 width, png_uint_32 height, - const VariantList& comments); + const VariantList& metaData); /** Load the PNG data from 'ReadInfo' into the FBSurface. The surface @@ -176,14 +177,14 @@ class PNGLibrary /** Write PNG tEXt chunks to the image. */ - void writeComments(const png_structp png_ptr, png_infop info_ptr, - const VariantList& comments); + void writeMetaData(const png_structp png_ptr, png_infop info_ptr, + const VariantList& metaData); /** Read PNG tEXt chunks from the image. */ - void readComments(const png_structp png_ptr, png_infop info_ptr, - VariantList& comments); + void readMetaData(const png_structp png_ptr, png_infop info_ptr, + VariantList& metaData); /** PNG library callback functions */ static void png_read_data(const png_structp ctx, png_bytep area, png_size_t size); diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 964574d68..20df8a76f 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -328,7 +328,7 @@ void LauncherDialog::addRomWidgets(int ypos) TIAConstants::viewableHeight * imgZoom); // Calculate font area, and in the process the font that can be used - // Infofont is unknown yet, but used in image label too. Assuming maximum font height. + // Infofont is unknown yet, but used in image label too. Assuming maximum font height. int imageHeight = imgSize.h + RomImageWidget::labelHeight(_font); const Common::Size fontArea(imageWidth - fontWidth * 2, @@ -676,16 +676,25 @@ void LauncherDialog::loadRomInfo() return; // Update ROM info UI item, delayed - myRomInfoTime = TimerManager::getTicks() / 1000 + 250; // TODO: define pending load delay + myRomInfoTime = TimerManager::getTicks() / 1000 + myRomImageWidget->pendingLoadTime(); myPendingRomInfo = true; const string& md5 = selectedRomMD5(); - if(md5 != EmptyString) + if(!md5.empty()) { - myRomImageWidget->setProperties(currentNode(), md5, false); - myRomInfoWidget->setProperties(currentNode(), md5, false); + // The properties for the currently selected ROM + Properties properties; + + // Make sure to load a per-ROM properties entry, if one exists + instance().propSet().loadPerROM(currentNode(), md5); + + // And now get the properties for this ROM + instance().propSet().getMD5(md5, properties); + + myRomImageWidget->setProperties(currentNode(), properties, false); + myRomInfoWidget->setProperties(currentNode(), properties, false); } - else + else { myRomImageWidget->clearProperties(); myRomInfoWidget->clearProperties(); @@ -703,8 +712,16 @@ void LauncherDialog::loadPendingRomInfo() const string& md5 = selectedRomMD5(); if(md5 != EmptyString) { - myRomImageWidget->setProperties(currentNode(), md5); - myRomInfoWidget->setProperties(currentNode(), md5); + // The properties for the currently selected ROM + Properties properties; + + // Make sure to load a per-ROM properties entry, if one exists + instance().propSet().loadPerROM(currentNode(), md5); + + // And now get the properties for this ROM + instance().propSet().getMD5(md5, properties); + myRomImageWidget->setProperties(currentNode(), properties); + myRomInfoWidget->setProperties(currentNode(), properties); } } diff --git a/src/gui/RomImageWidget.cxx b/src/gui/RomImageWidget.cxx index 17e5355bb..9d39e5650 100644 --- a/src/gui/RomImageWidget.cxx +++ b/src/gui/RomImageWidget.cxx @@ -25,13 +25,13 @@ #include "PNGLibrary.hxx" #include "Props.hxx" #include "PropsSet.hxx" +#include "TimerManager.hxx" #include "RomImageWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RomImageWidget::RomImageWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h) - : Widget(boss, font, x, y, w, h), - CommandSender(boss) + : Widget(boss, font, x, y, w, h) { _flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE; _bgcolor = kDlgColor; @@ -40,15 +40,10 @@ RomImageWidget::RomImageWidget(GuiObject* boss, const GUI::Font& font, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void RomImageWidget::setProperties(const FSNode& node, const string& md5, bool full) +void RomImageWidget::setProperties(const FSNode& node, const Properties properties, bool full) { myHaveProperties = true; - - // Make sure to load a per-ROM properties entry, if one exists - instance().propSet().loadPerROM(node, md5); - - // And now get the properties for this ROM - instance().propSet().getMD5(md5, myProperties); + myProperties = properties; // Decide whether the information should be shown immediately if(instance().eventHandler().state() == EventHandlerState::LAUNCHER) @@ -80,6 +75,7 @@ void RomImageWidget::reloadProperties(const FSNode& node) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomImageWidget::parseProperties(const FSNode& node, bool full) { + uInt64 startTime = TimerManager::getTicks() / 1000; if(myNavSurface == nullptr) { // Create navigation surface @@ -111,7 +107,7 @@ void RomImageWidget::parseProperties(const FSNode& node, bool full) }); } -#ifdef IMAGE_SUPPORT +#ifdef IMAGE_SUPPORT if(!full) { myImageIdx = 0; @@ -119,23 +115,24 @@ void RomImageWidget::parseProperties(const FSNode& node, bool full) // Get a valid filename representing a snapshot file for this rom and load the snapshot const string& path = instance().snapshotLoadDir().getPath(); + // 1. Try to load first snapshot by property name - string fileName = path + myProperties.get(PropType::Cart_Name);// +".png"; // TODO: try jpg - - tryImageTypes(fileName); - - loadImage(fileName); + string fileName = path + myProperties.get(PropType::Cart_Name); + tryImageFormats(fileName); if(!mySurfaceIsValid) { // 2. If none exists, try to load first snapshot by ROM file name - fileName = path + node.getNameWithExt("png"); // TODO: try jpg - loadImage(fileName); + fileName = path + node.getName(); + tryImageFormats(fileName); } if(mySurfaceIsValid) myImageList.emplace_back(fileName); else + { // 3. If no ROM snapshots exist, try to load a default snapshot - loadImage(path + "default_snapshot.png"); // TODO: try jpg??? + fileName = path + "default_snapshot"; + tryImageFormats(fileName); + } } else { @@ -152,11 +149,16 @@ void RomImageWidget::parseProperties(const FSNode& node, bool full) } #else mySurfaceIsValid = false; - mySurfaceErrorMsg = "PNG image loading not supported"; + mySurfaceErrorMsg = "Image loading not supported"; setDirty(); #endif if(mySurface) mySurface->setVisible(mySurfaceIsValid); + + // Update maximum load time + myMaxLoadTime = std::min( + static_cast(500ull / timeFactor), + std::max(myMaxLoadTime, TimerManager::getTicks() / 1000 - startTime)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -178,7 +180,7 @@ bool RomImageWidget::getImageList(const string& propName, const string& romName) const std::regex symbols{R"([-[\]{}()*+?.,\^$|#])"}; // \s const string rgxPropName = std::regex_replace(propName, symbols, R"(\$&)"); const string rgxRomName = std::regex_replace(romName, symbols, R"(\$&)"); - // Look for or (# is a number) + // Look for or (# is a number) const std::regex rgx("^(" + rgxPropName + "|" + rgxRomName + ")(_\\d+){0,1}\\.(png|jpg)$"); FSNode::NameFilter filter = ([&](const FSNode& node) @@ -191,15 +193,15 @@ bool RomImageWidget::getImageList(const string& propName, const string& romName) FSNode node(instance().snapshotLoadDir().getPath()); node.getChildren(myImageList, FSNode::ListMode::FilesOnly, filter, false, false); - // Sort again, not considering extensions, else would be at + // Sort again, not considering extensions, else would be at // the end of the list std::sort(myImageList.begin(), myImageList.end(), [](const FSNode& node1, const FSNode& node2) - { + { int compare = BSPF::compareIgnoreCase(node1.getNameWithExt(), node2.getNameWithExt()); - return + return compare < 0 || - (compare == 0 && + (compare == 0 && node1.getName().substr(node1.getName().find_last_of('.') + 1) > node2.getName().substr(node2.getName().find_last_of('.') + 1)); // PNGs first! } @@ -208,7 +210,7 @@ bool RomImageWidget::getImageList(const string& propName, const string& romName) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool RomImageWidget::tryImageTypes(string& fileName) +bool RomImageWidget::tryImageFormats(string& fileName) { if(loadImage(fileName + ".png")) { @@ -235,6 +237,15 @@ bool RomImageWidget::loadImage(const string& fileName) else mySurfaceIsValid = loadJpg(fileName); + if(mySurfaceIsValid) + { + // Scale surface to available image area + const Common::Rect& src = mySurface->srcRect(); + const float scale = std::min(float(_w) / src.w(), float(myImageHeight) / src.h()) * + instance().frameBuffer().hidpiScaleFactor(); + mySurface->setDstSize(static_cast(src.w() * scale), static_cast(src.h() * scale)); + } + if(mySurface) mySurface->setVisible(mySurfaceIsValid); @@ -247,27 +258,21 @@ bool RomImageWidget::loadPng(const string& fileName) { try { - VariantList comments; - instance().png().loadImage(fileName, *mySurface, comments); - - // Scale surface to available image area - const Common::Rect& src = mySurface->srcRect(); - const float scale = std::min(float(_w) / src.w(), float(myImageHeight) / src.h()) * - instance().frameBuffer().hidpiScaleFactor(); - mySurface->setDstSize(static_cast(src.w() * scale), static_cast(src.h() * scale)); + VariantList metaData; + instance().png().loadImage(fileName, *mySurface, metaData); // Retrieve label for loaded image myLabel.clear(); - for(auto comment = comments.begin(); comment != comments.end(); ++comment) + for(auto data = metaData.begin(); data != metaData.end(); ++data) { - if(comment->first == "Title") + if(data->first == "Title") { - myLabel = comment->second.toString(); + myLabel = data->second.toString(); break; } - if(comment->first == "Software" - && comment->second.toString().find("Stella") == 0) - myLabel = "Snapshot"; // default for Stella snapshots with missing "Title" comment + if(data->first == "Software" + && data->second.toString().find("Stella") == 0) + myLabel = "Snapshot"; // default for Stella snapshots with missing "Title" meta data } return true; } @@ -283,17 +288,17 @@ bool RomImageWidget::loadJpg(const string& fileName) { try { - VariantList comments; - instance().jpg().loadImage(fileName, *mySurface, comments); + VariantList metaData; + instance().jpg().loadImage(fileName, *mySurface, metaData); myLabel.clear(); + // TODO return true; } catch(const runtime_error& e) { mySurfaceErrorMsg = e.what(); - } - //mySurfaceErrorMsg = "JPG image loading not supported"; + } return false; } diff --git a/src/gui/RomImageWidget.hxx b/src/gui/RomImageWidget.hxx index 39e42257f..0d1df5123 100644 --- a/src/gui/RomImageWidget.hxx +++ b/src/gui/RomImageWidget.hxx @@ -23,7 +23,7 @@ class Properties; #include "Widget.hxx" -class RomImageWidget : public Widget, public CommandSender +class RomImageWidget : public Widget { public: RomImageWidget(GuiObject *boss, const GUI::Font& font, @@ -35,11 +35,13 @@ class RomImageWidget : public Widget, public CommandSender return font.getFontHeight() * 9 / 8; } - void setProperties(const FSNode& node, const string& md5, bool full = true); + void setProperties(const FSNode& node, const Properties properties, bool full = true); void clearProperties(); void reloadProperties(const FSNode& node); bool changeImage(int direction = 1); + uInt64 pendingLoadTime() { return myMaxLoadTime * timeFactor; } + protected: void drawWidget(bool hilite) override; #ifdef IMAGE_SUPPORT @@ -51,14 +53,18 @@ class RomImageWidget : public Widget, public CommandSender void parseProperties(const FSNode& node, bool full = true); #ifdef IMAGE_SUPPORT bool getImageList(const string& propName, const string& romName); - bool tryImageTypes(string& fileName); + bool tryImageFormats(string& fileName); bool loadImage(const string& fileName); bool loadPng(const string& fileName); bool loadJpg(const string& fileName); #endif private: - // Surface pointer holding the PNG image + // Pending load time safety factor + static constexpr double timeFactor = 1.2; + + private: + // Surface pointer holding the image shared_ptr mySurface; // Surface pointer holding the navigation elements @@ -91,6 +97,9 @@ class RomImageWidget : public Widget, public CommandSender // Label for the loaded image string myLabel; + // Maximum load time, for adapting pending loads delay + uInt64 myMaxLoadTime{0}; + private: // Following constructors and assignment operators not supported RomImageWidget() = delete; diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index a9366feb6..2cc4c0542 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -39,15 +39,10 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void RomInfoWidget::setProperties(const FSNode& node, const string& md5, bool full) +void RomInfoWidget::setProperties(const FSNode& node, const Properties properties, bool full) { myHaveProperties = true; - - // Make sure to load a per-ROM properties entry, if one exists - instance().propSet().loadPerROM(node, md5); - - // And now get the properties for this ROM - instance().propSet().getMD5(md5, myProperties); + myProperties = properties; // Decide whether the information should be shown immediately if(instance().eventHandler().state() == EventHandlerState::LAUNCHER) @@ -96,7 +91,7 @@ void RomInfoWidget::parseProperties(const FSNode& node, bool full) myRomInfo.push_back("Rarity: " + value); if((value = myProperties.get(PropType::Cart_Note)) != EmptyString) myRomInfo.push_back("Note: " + value); - + if(full) { const bool swappedPorts = myProperties.get(PropType::Console_SwapPorts) == "YES"; diff --git a/src/gui/RomInfoWidget.hxx b/src/gui/RomInfoWidget.hxx index a98fe5c0d..861139838 100644 --- a/src/gui/RomInfoWidget.hxx +++ b/src/gui/RomInfoWidget.hxx @@ -35,7 +35,7 @@ class RomInfoWidget : public Widget, public CommandSender int x, int y, int w, int h); ~RomInfoWidget() override = default; - void setProperties(const FSNode& node, const string& md5, bool full = true); + void setProperties(const FSNode& node, const Properties properties, bool full = true); void clearProperties(); void reloadProperties(const FSNode& node);