mirror of https://github.com/stella-emu/stella.git
made ROM info delay adaptive
some cleanup of the new JPG reading code
This commit is contained in:
parent
6e4710750f
commit
7691b2606f
|
@ -33,7 +33,7 @@ JPGLibrary::JPGLibrary(OSystem& osystem)
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void JPGLibrary::loadImage(const string& filename, FBSurface& surface,
|
void JPGLibrary::loadImage(const string& filename, FBSurface& surface,
|
||||||
VariantList& comments)
|
VariantList& metaData)
|
||||||
{
|
{
|
||||||
const auto loadImageERROR = [&](const char* s) {
|
const auto loadImageERROR = [&](const char* s) {
|
||||||
if(s)
|
if(s)
|
||||||
|
@ -63,8 +63,8 @@ void JPGLibrary::loadImage(const string& filename, FBSurface& surface,
|
||||||
myReadInfo.height = njGetHeight();
|
myReadInfo.height = njGetHeight();
|
||||||
myReadInfo.pitch = myReadInfo.width * 3;
|
myReadInfo.pitch = myReadInfo.width * 3;
|
||||||
|
|
||||||
// Read the comments we got TODO
|
// TODO: Read the meta data we got
|
||||||
//readComments(png_ptr, info_ptr, comments);
|
//readMetaData(png_ptr, info_ptr, metaData);
|
||||||
|
|
||||||
// Load image into the surface, setting the correct dimensions
|
// Load image into the surface, setting the correct dimensions
|
||||||
loadImagetoSurface(surface);
|
loadImagetoSurface(surface);
|
||||||
|
@ -103,8 +103,8 @@ void JPGLibrary::loadImagetoSurface(FBSurface& surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
//// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
//void JPGLibrary::readComments(const png_structp png_ptr, png_infop info_ptr,
|
//void JPGLibrary::readMetaData(const png_structp png_ptr, png_infop info_ptr,
|
||||||
// VariantList& comments)
|
// VariantList& metaData)
|
||||||
//{
|
//{
|
||||||
// png_textp text_ptr;
|
// png_textp text_ptr;
|
||||||
// int numComments = 0;
|
// int numComments = 0;
|
||||||
|
@ -112,10 +112,10 @@ void JPGLibrary::loadImagetoSurface(FBSurface& surface)
|
||||||
// // TODO: currently works only if comments are *before* the image data
|
// // 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, &numComments);
|
||||||
//
|
//
|
||||||
// comments.clear();
|
// metaData.clear();
|
||||||
// for(int i = 0; i < numComments; ++i)
|
// 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);
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,13 @@ class JPGLibrary
|
||||||
|
|
||||||
@param filename The filename to load the JPG image
|
@param filename The filename to load the JPG image
|
||||||
@param surface The FBSurface into which to place the JPG data
|
@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
|
@post On success, the FBSurface containing image data, otherwise a
|
||||||
runtime_error is thrown containing a more detailed
|
runtime_error is thrown containing a more detailed
|
||||||
error message.
|
error message.
|
||||||
*/
|
*/
|
||||||
void loadImage(const string& filename, FBSurface& surface, VariantList& comments);
|
void loadImage(const string& filename, FBSurface& surface, VariantList& metaData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Global OSystem object
|
// Global OSystem object
|
||||||
|
@ -70,10 +71,10 @@ class JPGLibrary
|
||||||
void loadImagetoSurface(FBSurface& surface);
|
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,
|
//void readmetaData(const png_structp png_ptr, png_infop info_ptr,
|
||||||
// VariantList& comments);
|
// VariantList& metaData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -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_structp png_ptr{nullptr};
|
||||||
png_infop info_ptr{nullptr};
|
png_infop info_ptr{nullptr};
|
||||||
|
@ -109,8 +109,8 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi
|
||||||
// We're finished reading
|
// We're finished reading
|
||||||
png_read_end(png_ptr, info_ptr);
|
png_read_end(png_ptr, info_ptr);
|
||||||
|
|
||||||
// Read the comments we got
|
// Read the meta data we got
|
||||||
readComments(png_ptr, info_ptr, comments);
|
readMetaData(png_ptr, info_ptr, metaData);
|
||||||
|
|
||||||
// Load image into the surface, setting the correct dimensions
|
// Load image into the surface, setting the correct dimensions
|
||||||
loadImagetoSurface(surface);
|
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);
|
std::ofstream out(filename, std::ios_base::binary);
|
||||||
if(!out.is_open())
|
if(!out.is_open())
|
||||||
|
@ -147,12 +147,12 @@ void PNGLibrary::saveImage(const string& filename, const VariantList& comments)
|
||||||
rows[k] = buffer.data() + k*width*4;
|
rows[k] = buffer.data() + k*width*4;
|
||||||
|
|
||||||
// And save the image
|
// 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,
|
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);
|
std::ofstream out(filename, std::ios_base::binary);
|
||||||
if(!out.is_open())
|
if(!out.is_open())
|
||||||
|
@ -176,12 +176,12 @@ void PNGLibrary::saveImage(const string& filename, const FBSurface& surface,
|
||||||
rows[k] = buffer.data() + k*width*4;
|
rows[k] = buffer.data() + k*width*4;
|
||||||
|
|
||||||
// And save the image
|
// And save the image
|
||||||
saveImageToDisk(out, rows, width, height, comments);
|
saveImageToDisk(out, rows, width, height, metaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PNGLibrary::saveImageToDisk(std::ofstream& out, const vector<png_bytep>& rows,
|
void PNGLibrary::saveImageToDisk(std::ofstream& out, const vector<png_bytep>& 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_structp png_ptr = nullptr;
|
||||||
png_infop info_ptr = nullptr;
|
png_infop info_ptr = nullptr;
|
||||||
|
@ -212,8 +212,8 @@ void PNGLibrary::saveImageToDisk(std::ofstream& out, const vector<png_bytep>& ro
|
||||||
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
||||||
PNG_FILTER_TYPE_DEFAULT);
|
PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
// Write comments
|
// Write meta data
|
||||||
writeComments(png_ptr, info_ptr, comments);
|
writeMetaData(png_ptr, info_ptr, metaData);
|
||||||
|
|
||||||
// Write the file header information. REQUIRED
|
// Write the file header information. REQUIRED
|
||||||
png_write_info(png_ptr, info_ptr);
|
png_write_info(png_ptr, info_ptr);
|
||||||
|
@ -331,18 +331,18 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
||||||
filename = sspath + ".png";
|
filename = sspath + ".png";
|
||||||
|
|
||||||
// Some text fields to add to the PNG snapshot
|
// Some text fields to add to the PNG snapshot
|
||||||
VariantList comments;
|
VariantList metaData;
|
||||||
ostringstream version;
|
ostringstream version;
|
||||||
VarList::push_back(comments, "Title", "Snapshot");
|
VarList::push_back(metaData, "Title", "Snapshot");
|
||||||
version << "Stella " << STELLA_VERSION << " (Build " << STELLA_BUILD << ") ["
|
version << "Stella " << STELLA_VERSION << " (Build " << STELLA_BUILD << ") ["
|
||||||
<< BSPF::ARCH << "]";
|
<< BSPF::ARCH << "]";
|
||||||
VarList::push_back(comments, "Software", version.str());
|
VarList::push_back(metaData, "Software", version.str());
|
||||||
const string& name = (myOSystem.settings().getString("snapname") == "int")
|
const string& name = (myOSystem.settings().getString("snapname") == "int")
|
||||||
? myOSystem.console().properties().get(PropType::Cart_Name)
|
? myOSystem.console().properties().get(PropType::Cart_Name)
|
||||||
: myOSystem.romFile().getName();
|
: myOSystem.romFile().getName();
|
||||||
VarList::push_back(comments, "ROM Name", name);
|
VarList::push_back(metaData, "ROM Name", name);
|
||||||
VarList::push_back(comments, "ROM MD5", myOSystem.console().properties().get(PropType::Cart_MD5));
|
VarList::push_back(metaData, "ROM MD5", myOSystem.console().properties().get(PropType::Cart_MD5));
|
||||||
VarList::push_back(comments, "TV Effects", myOSystem.frameBuffer().tiaSurface().effectsInfo());
|
VarList::push_back(metaData, "TV Effects", myOSystem.frameBuffer().tiaSurface().effectsInfo());
|
||||||
|
|
||||||
// Now create a PNG snapshot
|
// Now create a PNG snapshot
|
||||||
string message = "Snapshot saved";
|
string message = "Snapshot saved";
|
||||||
|
@ -352,7 +352,7 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
||||||
{
|
{
|
||||||
Common::Rect rect;
|
Common::Rect rect;
|
||||||
const FBSurface& surface = myOSystem.frameBuffer().tiaSurface().baseSurface(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)
|
catch(const runtime_error& e)
|
||||||
{
|
{
|
||||||
|
@ -367,7 +367,7 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
myOSystem.png().saveImage(filename, comments);
|
myOSystem.png().saveImage(filename, metaData);
|
||||||
}
|
}
|
||||||
catch(const runtime_error& e)
|
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,
|
void PNGLibrary::writeMetaData(const png_structp png_ptr, png_infop info_ptr,
|
||||||
const VariantList& comments)
|
const VariantList& metaData)
|
||||||
{
|
{
|
||||||
const uInt32 numComments = static_cast<uInt32>(comments.size());
|
const uInt32 numMetaData = static_cast<uInt32>(metaData.size());
|
||||||
if(numComments == 0)
|
if(numMetaData == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vector<png_text> text_ptr(numComments);
|
vector<png_text> text_ptr(numMetaData);
|
||||||
for(uInt32 i = 0; i < numComments; ++i)
|
for(uInt32 i = 0; i < numMetaData; ++i)
|
||||||
{
|
{
|
||||||
text_ptr[i].key = const_cast<char*>(comments[i].first.c_str());
|
text_ptr[i].key = const_cast<char*>(metaData[i].first.c_str());
|
||||||
text_ptr[i].text = const_cast<char*>(comments[i].second.toCString());
|
text_ptr[i].text = const_cast<char*>(metaData[i].second.toCString());
|
||||||
text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE;
|
text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||||
text_ptr[i].text_length = 0;
|
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,
|
void PNGLibrary::readMetaData(const png_structp png_ptr, png_infop info_ptr,
|
||||||
VariantList& comments)
|
VariantList& metaData)
|
||||||
{
|
{
|
||||||
png_textp text_ptr;
|
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, &numMetaData);
|
||||||
png_get_text(png_ptr, info_ptr, &text_ptr, &numComments);
|
|
||||||
|
|
||||||
comments.clear();
|
metaData.clear();
|
||||||
for(int i = 0; i < numComments; ++i)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,12 +43,13 @@ class PNGLibrary
|
||||||
|
|
||||||
@param filename The filename to load the PNG image
|
@param filename The filename to load the PNG image
|
||||||
@param surface The FBSurface into which to place the PNG data
|
@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
|
@post On success, the FBSurface containing image data, otherwise a
|
||||||
runtime_error is thrown containing a more detailed
|
runtime_error is thrown containing a more detailed
|
||||||
error message.
|
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
|
Save the current FrameBuffer image to a PNG file. Note that in most
|
||||||
|
@ -56,14 +57,14 @@ class PNGLibrary
|
||||||
*any* mode.
|
*any* mode.
|
||||||
|
|
||||||
@param filename The filename to save the PNG image
|
@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',
|
@post On success, the PNG file has been saved to 'filename',
|
||||||
otherwise a runtime_error is thrown containing a
|
otherwise a runtime_error is thrown containing a
|
||||||
more detailed error message.
|
more detailed error message.
|
||||||
*/
|
*/
|
||||||
void saveImage(const string& filename,
|
void saveImage(const string& filename,
|
||||||
const VariantList& comments = VariantList{});
|
const VariantList& metaData = VariantList{});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Save the given surface to a PNG file.
|
Save the given surface to a PNG file.
|
||||||
|
@ -71,7 +72,7 @@ class PNGLibrary
|
||||||
@param filename The filename to save the PNG image
|
@param filename The filename to save the PNG image
|
||||||
@param surface The surface data for the PNG image
|
@param surface The surface data for the PNG image
|
||||||
@param rect The area of the surface to use
|
@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',
|
@post On success, the PNG file has been saved to 'filename',
|
||||||
otherwise a runtime_error is thrown containing a
|
otherwise a runtime_error is thrown containing a
|
||||||
|
@ -79,7 +80,7 @@ class PNGLibrary
|
||||||
*/
|
*/
|
||||||
void saveImage(const string& filename, const FBSurface& surface,
|
void saveImage(const string& filename, const FBSurface& surface,
|
||||||
const Common::Rect& rect = Common::Rect{},
|
const Common::Rect& rect = Common::Rect{},
|
||||||
const VariantList& comments = VariantList{});
|
const VariantList& metaData = VariantList{});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Called at regular intervals, and used to determine whether a
|
Called at regular intervals, and used to determine whether a
|
||||||
|
@ -155,15 +156,15 @@ class PNGLibrary
|
||||||
|
|
||||||
/** The actual method which saves a PNG image.
|
/** The actual method which saves a PNG image.
|
||||||
|
|
||||||
@param out The output stream for writing PNG data
|
@param out The output stream for writing PNG data
|
||||||
@param rows Pointer into PNG RGB data for each row
|
@param rows Pointer into PNG RGB data for each row
|
||||||
@param width The width of the PNG image
|
@param width The width of the PNG image
|
||||||
@param height The height of the PNG image
|
@param height The height of the PNG image
|
||||||
@param comments The text comments to add to the PNG image
|
@param metaData The meta data to add to the PNG image
|
||||||
*/
|
*/
|
||||||
void saveImageToDisk(std::ofstream& out, const vector<png_bytep>& rows,
|
void saveImageToDisk(std::ofstream& out, const vector<png_bytep>& rows,
|
||||||
png_uint_32 width, png_uint_32 height,
|
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
|
Load the PNG data from 'ReadInfo' into the FBSurface. The surface
|
||||||
|
@ -176,14 +177,14 @@ class PNGLibrary
|
||||||
/**
|
/**
|
||||||
Write PNG tEXt chunks to the image.
|
Write PNG tEXt chunks to the image.
|
||||||
*/
|
*/
|
||||||
void writeComments(const png_structp png_ptr, png_infop info_ptr,
|
void writeMetaData(const png_structp png_ptr, png_infop info_ptr,
|
||||||
const VariantList& comments);
|
const VariantList& metaData);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Read PNG tEXt chunks from the image.
|
Read PNG tEXt chunks from the image.
|
||||||
*/
|
*/
|
||||||
void readComments(const png_structp png_ptr, png_infop info_ptr,
|
void readMetaData(const png_structp png_ptr, png_infop info_ptr,
|
||||||
VariantList& comments);
|
VariantList& metaData);
|
||||||
|
|
||||||
/** PNG library callback functions */
|
/** PNG library callback functions */
|
||||||
static void png_read_data(const png_structp ctx, png_bytep area, png_size_t size);
|
static void png_read_data(const png_structp ctx, png_bytep area, png_size_t size);
|
||||||
|
|
|
@ -676,14 +676,23 @@ void LauncherDialog::loadRomInfo()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Update ROM info UI item, delayed
|
// Update ROM info UI item, delayed
|
||||||
myRomInfoTime = TimerManager::getTicks() / 1000 + 250; // TODO: define pending load delay
|
myRomInfoTime = TimerManager::getTicks() / 1000 + myRomImageWidget->pendingLoadTime();
|
||||||
myPendingRomInfo = true;
|
myPendingRomInfo = true;
|
||||||
|
|
||||||
const string& md5 = selectedRomMD5();
|
const string& md5 = selectedRomMD5();
|
||||||
if(md5 != EmptyString)
|
if(!md5.empty())
|
||||||
{
|
{
|
||||||
myRomImageWidget->setProperties(currentNode(), md5, false);
|
// The properties for the currently selected ROM
|
||||||
myRomInfoWidget->setProperties(currentNode(), md5, false);
|
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
|
||||||
{
|
{
|
||||||
|
@ -703,8 +712,16 @@ void LauncherDialog::loadPendingRomInfo()
|
||||||
const string& md5 = selectedRomMD5();
|
const string& md5 = selectedRomMD5();
|
||||||
if(md5 != EmptyString)
|
if(md5 != EmptyString)
|
||||||
{
|
{
|
||||||
myRomImageWidget->setProperties(currentNode(), md5);
|
// The properties for the currently selected ROM
|
||||||
myRomInfoWidget->setProperties(currentNode(), md5);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
#include "PNGLibrary.hxx"
|
#include "PNGLibrary.hxx"
|
||||||
#include "Props.hxx"
|
#include "Props.hxx"
|
||||||
#include "PropsSet.hxx"
|
#include "PropsSet.hxx"
|
||||||
|
#include "TimerManager.hxx"
|
||||||
#include "RomImageWidget.hxx"
|
#include "RomImageWidget.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
RomImageWidget::RomImageWidget(GuiObject* boss, const GUI::Font& font,
|
RomImageWidget::RomImageWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
int x, int y, int w, int h)
|
int x, int y, int w, int h)
|
||||||
: Widget(boss, font, x, y, w, h),
|
: Widget(boss, font, x, y, w, h)
|
||||||
CommandSender(boss)
|
|
||||||
{
|
{
|
||||||
_flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE;
|
_flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE;
|
||||||
_bgcolor = kDlgColor;
|
_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;
|
myHaveProperties = true;
|
||||||
|
myProperties = properties;
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Decide whether the information should be shown immediately
|
// Decide whether the information should be shown immediately
|
||||||
if(instance().eventHandler().state() == EventHandlerState::LAUNCHER)
|
if(instance().eventHandler().state() == EventHandlerState::LAUNCHER)
|
||||||
|
@ -80,6 +75,7 @@ void RomImageWidget::reloadProperties(const FSNode& node)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void RomImageWidget::parseProperties(const FSNode& node, bool full)
|
void RomImageWidget::parseProperties(const FSNode& node, bool full)
|
||||||
{
|
{
|
||||||
|
uInt64 startTime = TimerManager::getTicks() / 1000;
|
||||||
if(myNavSurface == nullptr)
|
if(myNavSurface == nullptr)
|
||||||
{
|
{
|
||||||
// Create navigation surface
|
// Create navigation surface
|
||||||
|
@ -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
|
// Get a valid filename representing a snapshot file for this rom and load the snapshot
|
||||||
const string& path = instance().snapshotLoadDir().getPath();
|
const string& path = instance().snapshotLoadDir().getPath();
|
||||||
|
|
||||||
// 1. Try to load first snapshot by property name
|
// 1. Try to load first snapshot by property name
|
||||||
string fileName = path + myProperties.get(PropType::Cart_Name);// +".png"; // TODO: try jpg
|
string fileName = path + myProperties.get(PropType::Cart_Name);
|
||||||
|
tryImageFormats(fileName);
|
||||||
tryImageTypes(fileName);
|
|
||||||
|
|
||||||
loadImage(fileName);
|
|
||||||
if(!mySurfaceIsValid)
|
if(!mySurfaceIsValid)
|
||||||
{
|
{
|
||||||
// 2. If none exists, try to load first snapshot by ROM file name
|
// 2. If none exists, try to load first snapshot by ROM file name
|
||||||
fileName = path + node.getNameWithExt("png"); // TODO: try jpg
|
fileName = path + node.getName();
|
||||||
loadImage(fileName);
|
tryImageFormats(fileName);
|
||||||
}
|
}
|
||||||
if(mySurfaceIsValid)
|
if(mySurfaceIsValid)
|
||||||
myImageList.emplace_back(fileName);
|
myImageList.emplace_back(fileName);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
// 3. If no ROM snapshots exist, try to load a default snapshot
|
// 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
|
else
|
||||||
{
|
{
|
||||||
|
@ -152,11 +149,16 @@ void RomImageWidget::parseProperties(const FSNode& node, bool full)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
mySurfaceIsValid = false;
|
mySurfaceIsValid = false;
|
||||||
mySurfaceErrorMsg = "PNG image loading not supported";
|
mySurfaceErrorMsg = "Image loading not supported";
|
||||||
setDirty();
|
setDirty();
|
||||||
#endif
|
#endif
|
||||||
if(mySurface)
|
if(mySurface)
|
||||||
mySurface->setVisible(mySurfaceIsValid);
|
mySurface->setVisible(mySurfaceIsValid);
|
||||||
|
|
||||||
|
// Update maximum load time
|
||||||
|
myMaxLoadTime = std::min(
|
||||||
|
static_cast<uInt64>(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 std::regex symbols{R"([-[\]{}()*+?.,\^$|#])"}; // \s
|
||||||
const string rgxPropName = std::regex_replace(propName, symbols, R"(\$&)");
|
const string rgxPropName = std::regex_replace(propName, symbols, R"(\$&)");
|
||||||
const string rgxRomName = std::regex_replace(romName, symbols, R"(\$&)");
|
const string rgxRomName = std::regex_replace(romName, symbols, R"(\$&)");
|
||||||
// Look for <name.png> or <name_#.png> (# is a number)
|
// Look for <name.png|jpg> or <name_#.png|jpg> (# is a number)
|
||||||
const std::regex rgx("^(" + rgxPropName + "|" + rgxRomName + ")(_\\d+){0,1}\\.(png|jpg)$");
|
const std::regex rgx("^(" + rgxPropName + "|" + rgxRomName + ")(_\\d+){0,1}\\.(png|jpg)$");
|
||||||
|
|
||||||
FSNode::NameFilter filter = ([&](const FSNode& node)
|
FSNode::NameFilter filter = ([&](const FSNode& node)
|
||||||
|
@ -191,7 +193,7 @@ bool RomImageWidget::getImageList(const string& propName, const string& romName)
|
||||||
FSNode node(instance().snapshotLoadDir().getPath());
|
FSNode node(instance().snapshotLoadDir().getPath());
|
||||||
node.getChildren(myImageList, FSNode::ListMode::FilesOnly, filter, false, false);
|
node.getChildren(myImageList, FSNode::ListMode::FilesOnly, filter, false, false);
|
||||||
|
|
||||||
// Sort again, not considering extensions, else <filename.png> would be at
|
// Sort again, not considering extensions, else <filename.png|jpg> would be at
|
||||||
// the end of the list
|
// the end of the list
|
||||||
std::sort(myImageList.begin(), myImageList.end(),
|
std::sort(myImageList.begin(), myImageList.end(),
|
||||||
[](const FSNode& node1, const FSNode& node2)
|
[](const FSNode& node1, const FSNode& node2)
|
||||||
|
@ -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"))
|
if(loadImage(fileName + ".png"))
|
||||||
{
|
{
|
||||||
|
@ -235,6 +237,15 @@ bool RomImageWidget::loadImage(const string& fileName)
|
||||||
else
|
else
|
||||||
mySurfaceIsValid = loadJpg(fileName);
|
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<uInt32>(src.w() * scale), static_cast<uInt32>(src.h() * scale));
|
||||||
|
}
|
||||||
|
|
||||||
if(mySurface)
|
if(mySurface)
|
||||||
mySurface->setVisible(mySurfaceIsValid);
|
mySurface->setVisible(mySurfaceIsValid);
|
||||||
|
|
||||||
|
@ -247,27 +258,21 @@ bool RomImageWidget::loadPng(const string& fileName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
VariantList comments;
|
VariantList metaData;
|
||||||
instance().png().loadImage(fileName, *mySurface, comments);
|
instance().png().loadImage(fileName, *mySurface, metaData);
|
||||||
|
|
||||||
// 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<uInt32>(src.w() * scale), static_cast<uInt32>(src.h() * scale));
|
|
||||||
|
|
||||||
// Retrieve label for loaded image
|
// Retrieve label for loaded image
|
||||||
myLabel.clear();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if(comment->first == "Software"
|
if(data->first == "Software"
|
||||||
&& comment->second.toString().find("Stella") == 0)
|
&& data->second.toString().find("Stella") == 0)
|
||||||
myLabel = "Snapshot"; // default for Stella snapshots with missing "Title" comment
|
myLabel = "Snapshot"; // default for Stella snapshots with missing "Title" meta data
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -283,17 +288,17 @@ bool RomImageWidget::loadJpg(const string& fileName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
VariantList comments;
|
VariantList metaData;
|
||||||
instance().jpg().loadImage(fileName, *mySurface, comments);
|
instance().jpg().loadImage(fileName, *mySurface, metaData);
|
||||||
|
|
||||||
myLabel.clear();
|
myLabel.clear();
|
||||||
|
// TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch(const runtime_error& e)
|
catch(const runtime_error& e)
|
||||||
{
|
{
|
||||||
mySurfaceErrorMsg = e.what();
|
mySurfaceErrorMsg = e.what();
|
||||||
}
|
}
|
||||||
//mySurfaceErrorMsg = "JPG image loading not supported";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Properties;
|
||||||
|
|
||||||
#include "Widget.hxx"
|
#include "Widget.hxx"
|
||||||
|
|
||||||
class RomImageWidget : public Widget, public CommandSender
|
class RomImageWidget : public Widget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RomImageWidget(GuiObject *boss, const GUI::Font& font,
|
RomImageWidget(GuiObject *boss, const GUI::Font& font,
|
||||||
|
@ -35,11 +35,13 @@ class RomImageWidget : public Widget, public CommandSender
|
||||||
return font.getFontHeight() * 9 / 8;
|
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 clearProperties();
|
||||||
void reloadProperties(const FSNode& node);
|
void reloadProperties(const FSNode& node);
|
||||||
bool changeImage(int direction = 1);
|
bool changeImage(int direction = 1);
|
||||||
|
|
||||||
|
uInt64 pendingLoadTime() { return myMaxLoadTime * timeFactor; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void drawWidget(bool hilite) override;
|
void drawWidget(bool hilite) override;
|
||||||
#ifdef IMAGE_SUPPORT
|
#ifdef IMAGE_SUPPORT
|
||||||
|
@ -51,14 +53,18 @@ class RomImageWidget : public Widget, public CommandSender
|
||||||
void parseProperties(const FSNode& node, bool full = true);
|
void parseProperties(const FSNode& node, bool full = true);
|
||||||
#ifdef IMAGE_SUPPORT
|
#ifdef IMAGE_SUPPORT
|
||||||
bool getImageList(const string& propName, const string& romName);
|
bool getImageList(const string& propName, const string& romName);
|
||||||
bool tryImageTypes(string& fileName);
|
bool tryImageFormats(string& fileName);
|
||||||
bool loadImage(const string& fileName);
|
bool loadImage(const string& fileName);
|
||||||
bool loadPng(const string& fileName);
|
bool loadPng(const string& fileName);
|
||||||
bool loadJpg(const string& fileName);
|
bool loadJpg(const string& fileName);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
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<FBSurface> mySurface;
|
shared_ptr<FBSurface> mySurface;
|
||||||
|
|
||||||
// Surface pointer holding the navigation elements
|
// Surface pointer holding the navigation elements
|
||||||
|
@ -91,6 +97,9 @@ class RomImageWidget : public Widget, public CommandSender
|
||||||
// Label for the loaded image
|
// Label for the loaded image
|
||||||
string myLabel;
|
string myLabel;
|
||||||
|
|
||||||
|
// Maximum load time, for adapting pending loads delay
|
||||||
|
uInt64 myMaxLoadTime{0};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
RomImageWidget() = delete;
|
RomImageWidget() = delete;
|
||||||
|
|
|
@ -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;
|
myHaveProperties = true;
|
||||||
|
myProperties = properties;
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Decide whether the information should be shown immediately
|
// Decide whether the information should be shown immediately
|
||||||
if(instance().eventHandler().state() == EventHandlerState::LAUNCHER)
|
if(instance().eventHandler().state() == EventHandlerState::LAUNCHER)
|
||||||
|
|
|
@ -35,7 +35,7 @@ class RomInfoWidget : public Widget, public CommandSender
|
||||||
int x, int y, int w, int h);
|
int x, int y, int w, int h);
|
||||||
~RomInfoWidget() override = default;
|
~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 clearProperties();
|
||||||
void reloadProperties(const FSNode& node);
|
void reloadProperties(const FSNode& node);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue