diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 4f51f20bb5..33fecfe8d3 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -60,6 +60,11 @@ OverlayScreens="ScreenSystemLayer,ScreenSyncOverlay,ScreenStatsOverlay,ScreenDeb # Used in PlayerStageStats for formatting scores. PercentScoreDecimalPlaces=2 +# We want to define which Images to cache. +# Predefined Images include: Banner,Background,CDTitle,Jacket,CDImage,Disc +# Is Case Sensitive +ImageCache="Banner" + # 02 # [LightsManager] diff --git a/src/Banner.cpp b/src/Banner.cpp index a11a139bd9..00ad7b6457 100644 --- a/src/Banner.cpp +++ b/src/Banner.cpp @@ -1,6 +1,6 @@ #include "global.h" #include "Banner.h" -#include "BannerCache.h" +#include "ImageCache.h" #include "SongManager.h" #include "RageUtil.h" #include "Song.h" @@ -55,7 +55,7 @@ void Banner::LoadFromCachedBanner( const RString &sPath ) } RageTextureID ID; - bool bLowRes = (PREFSMAN->m_BannerCache != BNCACHE_FULL); + bool bLowRes = (PREFSMAN->m_ImageCache != IMGCACHE_FULL); if( !bLowRes ) { ID = Sprite::SongBannerTexture( sPath ); @@ -63,7 +63,7 @@ void Banner::LoadFromCachedBanner( const RString &sPath ) else { // Try to load the low quality version. - ID = BANNERCACHE->LoadCachedBanner( sPath ); + ID = IMAGECACHE->LoadCachedImage( "Banner", sPath ); } if( TEXTUREMAN->IsTextureRegistered(ID) ) diff --git a/src/CMakeData-data.cmake b/src/CMakeData-data.cmake index 03924720f7..134b73ff34 100644 --- a/src/CMakeData-data.cmake +++ b/src/CMakeData-data.cmake @@ -136,7 +136,7 @@ list(APPEND SM_DATA_REST_SRC "AdjustSync.cpp" "AutoKeysounds.cpp" "BackgroundUtil.cpp" - "BannerCache.cpp" + "ImageCache.cpp" "Character.cpp" "CodeDetector.cpp" "CodeSet.cpp" @@ -185,7 +185,7 @@ list(APPEND SM_DATA_REST_HPP "AdjustSync.h" "AutoKeysounds.h" "BackgroundUtil.h" - "BannerCache.h" + "ImageCache.h" "Character.h" "CodeDetector.h" "CodeSet.h" diff --git a/src/CommonMetrics.cpp b/src/CommonMetrics.cpp index 2d3eac4885..96e627dc5d 100644 --- a/src/CommonMetrics.cpp +++ b/src/CommonMetrics.cpp @@ -18,6 +18,7 @@ ThemeMetricDifficultiesToShow CommonMetrics::DIFFICULTIES_TO_SHOW ("Common","Di ThemeMetricStepsTypesToShow CommonMetrics::STEPS_TYPES_TO_SHOW ("Common","StepsTypesToHide"); ThemeMetric CommonMetrics::AUTO_SET_STYLE ("Common","AutoSetStyle"); ThemeMetric CommonMetrics::PERCENT_SCORE_DECIMAL_PLACES ("Common","PercentScoreDecimalPlaces"); +ThemeMetric CommonMetrics::IMAGES_TO_CACHE ("Common","ImageCache"); ThemeMetricDifficultiesToShow::ThemeMetricDifficultiesToShow( const RString& sGroup, const RString& sName ) : ThemeMetric(sGroup,sName) diff --git a/src/CommonMetrics.h b/src/CommonMetrics.h index ca4b0a439f..79b04f22df 100644 --- a/src/CommonMetrics.h +++ b/src/CommonMetrics.h @@ -60,6 +60,8 @@ namespace CommonMetrics extern ThemeMetric AUTO_SET_STYLE; /** @brief How many decimal places are used? */ extern ThemeMetric PERCENT_SCORE_DECIMAL_PLACES; + + extern ThemeMetric IMAGES_TO_CACHE; RString LocalizeOptionItem( const RString &s, bool bOptional ); }; diff --git a/src/FadingBanner.cpp b/src/FadingBanner.cpp index c6db394380..3f43ce52ec 100644 --- a/src/FadingBanner.cpp +++ b/src/FadingBanner.cpp @@ -1,7 +1,7 @@ #include "global.h" #include "FadingBanner.h" #include "RageTextureManager.h" -#include "BannerCache.h" +#include "ImageCache.h" #include "Song.h" #include "RageLog.h" #include "PrefsManager.h" @@ -128,7 +128,7 @@ bool FadingBanner::LoadFromCachedBanner( const RString &path ) * which will cause the fade-in to be further delayed. */ RageTextureID ID; - bool bLowRes = (PREFSMAN->m_BannerCache != BNCACHE_FULL); + bool bLowRes = (PREFSMAN->m_ImageCache != IMGCACHE_FULL); if( !bLowRes ) { ID = Sprite::SongBannerTexture( path ); @@ -136,7 +136,7 @@ bool FadingBanner::LoadFromCachedBanner( const RString &path ) else { // Try to load the low quality version. - ID = BANNERCACHE->LoadCachedBanner( path ); + ID = IMAGECACHE->LoadCachedImage( "Banner", path ); } if( !TEXTUREMAN->IsTextureRegistered(ID) ) diff --git a/src/BannerCache.cpp b/src/ImageCache.cpp similarity index 54% rename from src/BannerCache.cpp rename to src/ImageCache.cpp index ffe62a0cae..731aa77a10 100644 --- a/src/BannerCache.cpp +++ b/src/ImageCache.cpp @@ -1,6 +1,6 @@ #include "global.h" -#include "BannerCache.h" +#include "ImageCache.h" #include "Foreach.h" #include "RageDisplay.h" #include "RageUtil.h" @@ -19,184 +19,184 @@ #include "RageSurfaceUtils_Zoom.h" #include "SpecialFiles.h" -#include "Banner.h" +//#include "Banner.h" -static Preference g_bPalettedBannerCache( "PalettedBannerCache", false ); +static Preference g_bPalettedImageCache( "PalettedImageCache", false ); /* Neither a global or a file scope static can be used for this because * the order of initialization of nonlocal objects is unspecified. */ -//const RString BANNER_CACHE_INDEX = SpecialFiles::CACHE_DIR + "banners.cache"; -#define BANNER_CACHE_INDEX (SpecialFiles::CACHE_DIR + "banners.cache") +//const std::string IMAGE_CACHE_INDEX = SpecialFiles::CACHE_DIR + "images.cache"; +#define IMAGE_CACHE_INDEX (SpecialFiles::CACHE_DIR + "images.cache") -/* Call CacheBanner to cache a banner by path. If the banner is already - * cached, it'll be recreated. This is efficient if the banner hasn't changed, +/* Call CacheImage to cache a image by path. If the image is already + * cached, it'll be recreated. This is efficient if the image hasn't changed, * but we still only do this in TidyUpData for songs. * - * Call LoadBanner to load a cached banner into main memory. This will call - * CacheBanner only if needed. This will not do a date/size check; call CacheBanner + * Call LoadImage to load a cached image into main memory. This will call + * CacheImage only if needed. This will not do a date/size check; call CacheImage * directly if you need that. * - * Call LoadCachedBanner to load a banner into a texture and retrieve an ID - * for it. You can check if the banner was actually preloaded by calling - * TEXTUREMAN->IsTextureRegistered() on the ID; it might not be if the banner cache + * Call LoadCachedImage to load a image into a texture and retrieve an ID + * for it. You can check if the image was actually preloaded by calling + * TEXTUREMAN->IsTextureRegistered() on the ID; it might not be if the image cache * is missing or disabled. * * Note that each cache entries has two hashes. The cache path is based soley * on the pathname; this way, loading the cache doesn't have to do a stat on every - * banner. The full hash includes the file size and date, and is used only by - * CacheBanner to avoid doing extra work. + * image. The full hash includes the file size and date, and is used only by + * CacheImage to avoid doing extra work. */ -BannerCache *BANNERCACHE; // global and accessible from anywhere in our program +ImageCache *IMAGECACHE; // global and accessible from anywhere in our program -static map g_BannerPathToImage; +static map g_ImagePathToImage; static int g_iDemandRefcount = 0; -RString BannerCache::GetBannerCachePath( const RString &sBannerPath ) +std::string ImageCache::GetImageCachePath( const std::string &sImageDir, const std::string &sImagePath ) { - return SongCacheIndex::GetCacheFilePath( "Banners", sBannerPath ); + return SongCacheIndex::GetCacheFilePath( sImageDir, sImagePath ); } -/* If in on-demand mode, load all cached banners. This must be fast, so +/* If in on-demand mode, load all cached images. This must be fast, so * cache files will not be created if they don't exist; that should be done - * by CacheBanner or LoadBanner on startup. */ -void BannerCache::Demand() + * by CacheImage or LoadImage on startup. */ +void ImageCache::Demand( const std::string &sImageDir ) { ++g_iDemandRefcount; if( g_iDemandRefcount > 1 ) return; - if( PREFSMAN->m_BannerCache != BNCACHE_LOW_RES_LOAD_ON_DEMAND ) + if( PREFSMAN->m_ImageCache != IMGCACHE_LOW_RES_LOAD_ON_DEMAND ) return; - FOREACH_CONST_Child( &BannerData, p ) + FOREACH_CONST_Child( &ImageData, p ) { - RString sBannerPath = p->GetName(); + std::string sImagePath = p->GetName(); - if( g_BannerPathToImage.find(sBannerPath) != g_BannerPathToImage.end() ) + if( g_ImagePathToImage.find(sImagePath) != g_ImagePathToImage.end() ) continue; /* already loaded */ - const RString sCachePath = GetBannerCachePath(sBannerPath); + const std::string sCachePath = GetImageCachePath(sImageDir,sImagePath); RageSurface *pImage = RageSurfaceUtils::LoadSurface( sCachePath ); if( pImage == NULL ) { continue; /* doesn't exist */ } - g_BannerPathToImage[sBannerPath] = pImage; + g_ImagePathToImage[sImagePath] = pImage; } } -/* Release banners loaded on demand. */ -void BannerCache::Undemand() +/* Release images loaded on demand. */ +void ImageCache::Undemand( const std::string &sImageDir ) { --g_iDemandRefcount; if( g_iDemandRefcount != 0 ) return; - if( PREFSMAN->m_BannerCache != BNCACHE_LOW_RES_LOAD_ON_DEMAND ) + if( PREFSMAN->m_ImageCache != IMGCACHE_LOW_RES_LOAD_ON_DEMAND ) return; - UnloadAllBanners(); + UnloadAllImages(); } -/* If in a low-res banner mode, load a low-res banner into memory, creating - * the cache file if necessary. Unlike CacheBanner(), the original file will - * not be examined unless the cached banner doesn't exist, so the banner will +/* If in a low-res image mode, load a low-res image into memory, creating + * the cache file if necessary. Unlike CacheImage(), the original file will + * not be examined unless the cached image doesn't exist, so the image will * not be updated if the original file changes, for efficiency. */ -void BannerCache::LoadBanner( const RString &sBannerPath ) +void ImageCache::LoadImage( const std::string &sImageDir, const std::string &sImagePath ) { - if( sBannerPath == "" ) + if( sImagePath == "" ) return; // nothing to do - if( PREFSMAN->m_BannerCache != BNCACHE_LOW_RES_PRELOAD && - PREFSMAN->m_BannerCache != BNCACHE_LOW_RES_LOAD_ON_DEMAND ) + if( PREFSMAN->m_ImageCache != IMGCACHE_LOW_RES_PRELOAD && + PREFSMAN->m_ImageCache != IMGCACHE_LOW_RES_LOAD_ON_DEMAND ) return; /* Load it. */ - const RString sCachePath = GetBannerCachePath(sBannerPath); + const std::string sCachePath = GetImageCachePath(sImageDir,sImagePath); for( int tries = 0; tries < 2; ++tries ) { - if( g_BannerPathToImage.find(sBannerPath) != g_BannerPathToImage.end() ) + if( g_ImagePathToImage.find(sImagePath) != g_ImagePathToImage.end() ) return; /* already loaded */ - CHECKPOINT_M( ssprintf( "BannerCache::LoadBanner: %s", sCachePath.c_str() ) ); + CHECKPOINT_M( ssprintf( "ImageCache::LoadImage: %s", sCachePath.c_str() ) ); RageSurface *pImage = RageSurfaceUtils::LoadSurface( sCachePath ); if( pImage == nullptr ) { if( tries == 0 ) { - /* The file doesn't exist. It's possible that the banner cache file is + /* The file doesn't exist. It's possible that the image cache file is * missing, so try to create it. Don't do this first, for efficiency. */ - //LOG->Trace( "Cached banner load of '%s' ('%s') failed, trying to cache ...", sBannerPath.c_str(), sCachePath.c_str() ); + //LOG->Trace( "Cached image load of '%s' ('%s') failed, trying to cache ...", sImagePath.c_str(), sCachePath.c_str() ); /* Skip the up-to-date check; it failed to load, so it can't be up * to date. */ - CacheBannerInternal( sBannerPath ); + CacheImageInternal( sImageDir, sImagePath ); continue; } else { - //LOG->Trace( "Cached banner load of '%s' ('%s') failed", sBannerPath.c_str(), sCachePath.c_str() ); + //LOG->Trace( "Cached image load of '%s' ('%s') failed", sImagePath.c_str(), sCachePath.c_str() ); return; } } - g_BannerPathToImage[sBannerPath] = pImage; + g_ImagePathToImage[sImagePath] = pImage; } } -void BannerCache::OutputStats() const +void ImageCache::OutputStats() const { int iTotalSize = 0; - FOREACHM_CONST( RString, RageSurface *, g_BannerPathToImage, it ) + FOREACHM_CONST( std::string, RageSurface *, g_ImagePathToImage, it ) { const RageSurface *pImage = it->second; const int iSize = pImage->pitch * pImage->h; iTotalSize += iSize; } - LOG->Info( "%i bytes of banners loaded", iTotalSize ); + LOG->Info( "%i bytes of images loaded", iTotalSize ); } -void BannerCache::UnloadAllBanners() +void ImageCache::UnloadAllImages() { - FOREACHM( RString, RageSurface *, g_BannerPathToImage, it ) + FOREACHM( std::string, RageSurface *, g_ImagePathToImage, it ) delete it->second; - g_BannerPathToImage.clear(); + g_ImagePathToImage.clear(); } -BannerCache::BannerCache() +ImageCache::ImageCache() { ReadFromDisk(); } -BannerCache::~BannerCache() +ImageCache::~ImageCache() { - UnloadAllBanners(); + UnloadAllImages(); } -void BannerCache::ReadFromDisk() +void ImageCache::ReadFromDisk() { - BannerData.ReadFile( BANNER_CACHE_INDEX ); // don't care if this fails + ImageData.ReadFile( IMAGE_CACHE_INDEX ); // don't care if this fails } -struct BannerTexture: public RageTexture +struct ImageTexture: public RageTexture { unsigned m_uTexHandle; unsigned GetTexHandle() const override { return m_uTexHandle; }; // accessed by RageDisplay - /* This is a reference to a pointer in g_BannerPathToImage. */ + /* This is a reference to a pointer in g_ImagePathToImage. */ RageSurface *&m_pImage; int m_iWidth, m_iHeight; - BannerTexture( RageTextureID id, RageSurface *&pImage, int iWidth, int iHeight ): + ImageTexture( RageTextureID id, RageSurface *&pImage, int iWidth, int iHeight ): RageTexture(id), m_pImage(pImage), m_iWidth(iWidth), m_iHeight(iHeight) { Create(); } - ~BannerTexture() override + ~ImageTexture() override { Destroy(); } @@ -264,53 +264,54 @@ struct BannerTexture: public RageTexture } }; -/* If a banner is cached, get its ID for use. */ -RageTextureID BannerCache::LoadCachedBanner( const RString &sBannerPath ) +/* If a image is cached, get its ID for use. */ +RageTextureID ImageCache::LoadCachedImage( const std::string &sImageDir, const std::string &sImagePath ) { - RageTextureID ID( GetBannerCachePath(sBannerPath) ); + RageTextureID ID( GetImageCachePath(sImageDir,sImagePath) ); - if( sBannerPath == "" ) + if( sImagePath == "" ) return ID; - //LOG->Trace( "BannerCache::LoadCachedBanner(%s): %s", sBannerPath.c_str(), ID.filename.c_str() ); + //LOG->Trace( "ImageCache::LoadCachedImage(%s): %s", sImagePath.c_str(), ID.filename.c_str() ); - /* Hack: make sure Banner::Load doesn't change our return value and end up + /* Hack: make sure Image::Load doesn't change our return value and end up * reloading. */ - ID = Sprite::SongBannerTexture(ID); + if(sImageDir == "Banner") + ID = Sprite::SongBannerTexture(ID); /* It's not in a texture. Do we have it loaded? */ - if( g_BannerPathToImage.find(sBannerPath) == g_BannerPathToImage.end() ) + if( g_ImagePathToImage.find(sImagePath) == g_ImagePathToImage.end() ) { /* Oops, the image is missing. Warn and continue. */ - if(PREFSMAN->m_BannerCache != BNCACHE_OFF) + if(PREFSMAN->m_ImageCache != IMGCACHE_OFF) { - LOG->Warn( "Banner cache for '%s' wasn't loaded", sBannerPath.c_str() ); + LOG->Warn( "%s cache for '%s' wasn't loaded", sImageDir.c_str(), sImagePath.c_str() ); } return ID; } - /* This is a reference to a pointer. BannerTexture's ctor may change it + /* This is a reference to a pointer. ImageTexture's ctor may change it * when converting; this way, the conversion will end up in the map so we * only have to convert once. */ - RageSurface *&pImage = g_BannerPathToImage[sBannerPath]; + RageSurface *&pImage = g_ImagePathToImage[sImagePath]; ASSERT( pImage != nullptr ); int iSourceWidth = 0, iSourceHeight = 0; - BannerData.GetValue( sBannerPath, "Width", iSourceWidth ); - BannerData.GetValue( sBannerPath, "Height", iSourceHeight ); + ImageData.GetValue( sImagePath, "Width", iSourceWidth ); + ImageData.GetValue( sImagePath, "Height", iSourceHeight ); if( iSourceWidth == 0 || iSourceHeight == 0 ) { - LOG->UserLog( "Cache file", sBannerPath, "couldn't be loaded." ); + LOG->UserLog( "Cache file", sImagePath, "couldn't be loaded." ); return ID; } - /* Is the banner already in a texture? */ + /* Is the image already in a texture? */ if( TEXTUREMAN->IsTextureRegistered(ID) ) return ID; /* It's all set. */ - //LOG->Trace( "Loading banner texture %s; src %ix%i; image %ix%i", + //LOG->Trace( "Loading image texture %s; src %ix%i; image %ix%i", // ID.filename.c_str(), iSourceWidth, iSourceHeight, pImage->w, pImage->h ); - RageTexture *pTexture = new BannerTexture( ID, pImage, iSourceWidth, iSourceHeight ); + RageTexture *pTexture = new ImageTexture( ID, pImage, iSourceWidth, iSourceHeight ); ID.Policy = RageTextureID::TEX_VOLATILE; TEXTUREMAN->RegisterTexture( ID, pTexture ); @@ -326,19 +327,20 @@ static inline int closest( int num, int n1, int n2 ) return n1; } -/* Create or update the banner cache file as necessary. If in preload mode, +/* Create or update the image cache file as necessary. If in preload mode, * load the cache file, too. (This is done at startup.) */ -void BannerCache::CacheBanner( const RString &sBannerPath ) +void ImageCache::CacheImage( const std::string &sImageDir, const std::string &sImagePath ) { - if( PREFSMAN->m_BannerCache != BNCACHE_LOW_RES_PRELOAD && - PREFSMAN->m_BannerCache != BNCACHE_LOW_RES_LOAD_ON_DEMAND ) + if( PREFSMAN->m_ImageCache != IMGCACHE_LOW_RES_PRELOAD && + PREFSMAN->m_ImageCache != IMGCACHE_LOW_RES_LOAD_ON_DEMAND ) return; - CHECKPOINT_M( sBannerPath ); - if( !DoesFileExist(sBannerPath) ) + RString otImagePath = sImagePath; // Remove this when Global RString to std::string convert. + CHECKPOINT_M( otImagePath ); + if( !DoesFileExist(sImagePath) ) return; - const RString sCachePath = GetBannerCachePath(sBannerPath); + const std::string sCachePath = GetImageCachePath(sImageDir,sImagePath); /* Check the full file hash. If it's the loaded and identical, don't recache. */ if( DoesFileExist(sCachePath) ) @@ -347,41 +349,45 @@ void BannerCache::CacheBanner( const RString &sBannerPath ) if( !bCacheUpToDate ) { unsigned CurFullHash; - const unsigned FullHash = GetHashForFile( sBannerPath ); - if( BannerData.GetValue( sBannerPath, "FullHash", CurFullHash ) && CurFullHash == FullHash ) + const unsigned FullHash = GetHashForFile( sImagePath ); + if( ImageData.GetValue( sImagePath, "FullHash", CurFullHash ) && CurFullHash == FullHash ) bCacheUpToDate = true; } if( bCacheUpToDate ) { /* It's identical. Just load it, if in preload. */ - if( PREFSMAN->m_BannerCache == BNCACHE_LOW_RES_PRELOAD ) - LoadBanner( sBannerPath ); - + if( PREFSMAN->m_ImageCache == IMGCACHE_LOW_RES_PRELOAD ) + LoadImage( sImageDir, sImagePath ); + return; } } /* The cache file doesn't exist, or is out of date. Cache it. This * will also load the cache into memory if in PRELOAD. */ - CacheBannerInternal( sBannerPath ); + CacheImageInternal( sImageDir, sImagePath ); } -void BannerCache::CacheBannerInternal( const RString &sBannerPath ) +void ImageCache::CacheImageInternal( const std::string &sImageDir, const std::string &sImagePath ) { - RString sError; - RageSurface *pImage = RageSurfaceUtils::LoadFile( sBannerPath, sError ); + std::string sError; + RString otImagePath = sImagePath; RString otError = sError; // Remove this when Global RString to std::string convert. + RageSurface *pImage = RageSurfaceUtils::LoadFile( otImagePath, otError ); if( pImage == nullptr ) { - LOG->UserLog( "Cache file", sBannerPath, "couldn't be loaded: %s", sError.c_str() ); + LOG->UserLog( "Cache file", sImagePath, "couldn't be loaded: %s", sError.c_str() ); return; } const int iSourceWidth = pImage->w, iSourceHeight = pImage->h; - // cap banners to reasonable dimensions....? -mina - int iWidth = min(pImage->w, 256), iHeight = min(pImage->h, 64); - + // cap images to reasonable dimensions....? -mina + // int iWidth = min(pImage->w, 256), iHeight = min(pImage->h, 64); + + // I rather have it Cache everything -Jousway + int iWidth = pImage->w / 2.5, iHeight = pImage->h / 2.5; + /* Round to the nearest power of two. This simplifies the actual texture load. */ iWidth = closest( iWidth, power_of_two(iWidth), power_of_two(iWidth) / 2 ); iHeight = closest( iHeight, power_of_two(iHeight), power_of_two(iHeight) / 2 ); @@ -396,22 +402,22 @@ void BannerCache::CacheBannerInternal( const RString &sBannerPath ) RageSurfaceUtils::Zoom( pImage, iWidth, iHeight ); /* - * When paletted banner cache is enabled, cached banners are paletted. Cached - * 32-bit banners take 1/16 as much memory, 16-bit banners take 1/8, and paletted - * banners take 1/4. + * When paletted image cache is enabled, cached images are paletted. Cached + * 32-bit images take 1/16 as much memory, 16-bit images take 1/8, and paletted + * images take 1/4. * - * When paletted banner cache is disabled, cached banners are stored in 16-bit - * RGBA. Cached 32-bit banners take 1/8 as much memory, cached 16-bit banners - * take 1/4, and cached paletted banners take 1/2. + * When paletted image cache is disabled, cached images are stored in 16-bit + * RGBA. Cached 32-bit images take 1/8 as much memory, cached 16-bit images + * take 1/4, and cached paletted images take 1/2. * * Paletted cache is disabled by default because palettization takes time, causing * the initial cache run to take longer. Also, newer ATI hardware doesn't supported * paletted textures, which would slow down runtime, because we have to depalettize * on use. They'd still have the same memory benefits, though, since we only load - * one cached banner into a texture at once, and the speed hit may not matter on + * one cached image into a texture at once, and the speed hit may not matter on * newer ATI cards. RGBA is safer, though. */ - if( g_bPalettedBannerCache ) + if( g_bPalettedImageCache ) { if( pImage->fmt.BytesPerPixel != 1 ) RageSurfaceUtils::Palettize( pImage ); @@ -430,31 +436,31 @@ void BannerCache::CacheBannerInternal( const RString &sBannerPath ) pImage = dst; } - const RString sCachePath = GetBannerCachePath(sBannerPath); + const std::string sCachePath = GetImageCachePath(sImageDir,sImagePath); RageSurfaceUtils::SaveSurface( pImage, sCachePath ); /* If an old image is loaded, free it. */ - if( g_BannerPathToImage.find(sBannerPath) != g_BannerPathToImage.end() ) + if( g_ImagePathToImage.find(sImagePath) != g_ImagePathToImage.end() ) { - RageSurface *oldimg = g_BannerPathToImage[sBannerPath]; + RageSurface *oldimg = g_ImagePathToImage[sImagePath]; delete oldimg; - g_BannerPathToImage.erase(sBannerPath); + g_ImagePathToImage.erase(sImagePath); } - if( PREFSMAN->m_BannerCache == BNCACHE_LOW_RES_PRELOAD ) + if( PREFSMAN->m_ImageCache == IMGCACHE_LOW_RES_PRELOAD ) { /* Keep it; we're just going to load it anyway. */ - g_BannerPathToImage[sBannerPath] = pImage; + g_ImagePathToImage[sImagePath] = pImage; } else delete pImage; /* Remember the original size. */ - BannerData.SetValue( sBannerPath, "Path", sCachePath ); - BannerData.SetValue( sBannerPath, "Width", iSourceWidth ); - BannerData.SetValue( sBannerPath, "Height", iSourceHeight ); - BannerData.SetValue( sBannerPath, "FullHash", GetHashForFile( sBannerPath ) ); - BannerData.WriteFile( BANNER_CACHE_INDEX ); + ImageData.SetValue( sImagePath, "Path", sCachePath ); + ImageData.SetValue( sImagePath, "Width", iSourceWidth ); + ImageData.SetValue( sImagePath, "Height", iSourceHeight ); + ImageData.SetValue( sImagePath, "FullHash", GetHashForFile( sImagePath ) ); + ImageData.WriteFile( IMAGE_CACHE_INDEX ); } /* diff --git a/src/BannerCache.h b/src/ImageCache.h similarity index 67% rename from src/BannerCache.h rename to src/ImageCache.h index 3fed272995..1d26cda7d6 100644 --- a/src/BannerCache.h +++ b/src/ImageCache.h @@ -1,5 +1,5 @@ -#ifndef BANNER_CACHE_H -#define BANNER_CACHE_H +#ifndef IMAGE_CACHE_H +#define IMAGE_CACHE_H #include "IniFile.h" @@ -7,31 +7,31 @@ class LoadingWindow; /** @brief Maintains a cache of reduced-quality banners. */ -class BannerCache +class ImageCache { public: - BannerCache(); - ~BannerCache(); + ImageCache(); + ~ImageCache(); void ReadFromDisk(); - RageTextureID LoadCachedBanner( const RString &sBannerPath ); - void CacheBanner( const RString &sBannerPath ); - void LoadBanner( const RString &sBannerPath ); + RageTextureID LoadCachedImage( const std::string &sImageDir, const std::string &sImagePath ); + void CacheImage( const std::string &sImageDir, const std::string &sImagePath ); + void LoadImage( const std::string &sImageDir, const std::string &sImagePath ); - void Demand(); - void Undemand(); + void Demand( const std::string &sImageDir ); + void Undemand( const std::string &sImageDir ); void OutputStats() const; private: - static RString GetBannerCachePath( const RString &sBannerPath ); - void UnloadAllBanners(); - void CacheBannerInternal( const RString &sBannerPath ); + static std::string GetImageCachePath( const std::string &sImageDir, const std::string &sImagePath ); + void UnloadAllImages(); + void CacheImageInternal( const std::string &sImageDir, const std::string &sImagePath ); - IniFile BannerData; + IniFile ImageData; }; -extern BannerCache *BANNERCACHE; // global and accessible from anywhere in our program +extern ImageCache *IMAGECACHE; // global and accessible from anywhere in our program #endif diff --git a/src/Makefile.am b/src/Makefile.am index 1645fa5ae4..1971d55a56 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -131,7 +131,7 @@ DataStructures = \ Attack.cpp Attack.h AutoKeysounds.cpp AutoKeysounds.h \ AdjustSync.cpp AdjustSync.h \ BackgroundUtil.cpp BackgroundUtil.h \ -BannerCache.cpp BannerCache.h \ +ImageCache.cpp ImageCache.h \ Character.cpp Character.h \ CodeDetector.cpp CodeDetector.h \ CodeSet.cpp CodeSet.h \ diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index 4423afdbc4..8581c00581 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -77,26 +77,16 @@ XToString( ShowDancingCharacters ); StringToX( ShowDancingCharacters ); LuaXType( ShowDancingCharacters ); -static const char *BannerCacheModeNames[] = { +static const char *ImageCacheModeNames[] = { "Off", "LowResPreload", "LowResLoadOnDemand", "Full" }; -XToString( BannerCacheMode ); -StringToX( BannerCacheMode ); -LuaXType( BannerCacheMode ); -/* -static const char *BackgroundCacheModeNames[] = { - "Off", - "LowResPreload", - "LowResLoadOnDemand", - "Full" -}; -XToString( BackgroundCacheMode ); -StringToX( BackgroundCacheMode ); -LuaXType( BackgroundCacheMode ); -*/ +XToString( ImageCacheMode ); +StringToX( ImageCacheMode ); +LuaXType( ImageCacheMode ); + static const char *HighResolutionTexturesNames[] = { "Auto", "ForceOff", @@ -173,8 +163,7 @@ PrefsManager::PrefsManager() : m_bPAL ( "PAL", false ), m_bDelayedTextureDelete ( "DelayedTextureDelete", false ), m_bDelayedModelDelete ( "DelayedModelDelete", false ), - m_BannerCache ( "BannerCache", BNCACHE_LOW_RES_PRELOAD ), - //m_BackgroundCache ( "BackgroundCache", BGCACHE_LOW_RES_PRELOAD ), + m_ImageCache ( "ImageCache", IMGCACHE_LOW_RES_PRELOAD ), m_bFastLoad ( "FastLoad", true ), m_bFastLoadAdditionalSongs ( "FastLoadAdditionalSongs", true ), m_NeverCacheList ( "NeverCacheList", ""), diff --git a/src/PrefsManager.h b/src/PrefsManager.h index ddb2fa79c5..845d386a61 100644 --- a/src/PrefsManager.h +++ b/src/PrefsManager.h @@ -57,26 +57,15 @@ enum ShowDancingCharacters NUM_ShowDancingCharacters, ShowDancingCharacters_Invalid }; -enum BannerCacheMode +enum ImageCacheMode { - BNCACHE_OFF, - BNCACHE_LOW_RES_PRELOAD, // preload low-res on start - BNCACHE_LOW_RES_LOAD_ON_DEMAND, // preload low-res on screen load - BNCACHE_FULL, - NUM_BannerCacheMode, - BannerCacheMode_Invalid + IMGCACHE_OFF, + IMGCACHE_LOW_RES_PRELOAD, // preload low-res on start + IMGCACHE_LOW_RES_LOAD_ON_DEMAND, // preload low-res on screen load + IMGCACHE_FULL, + NUM_ImageCacheMode, + ImageCacheMode_Invalid }; -/* -enum BackgroundCacheMode -{ - BGCACHE_OFF, - BGCACHE_LOW_RES_PRELOAD, // preload low-res on start - BGCACHE_LOW_RES_LOAD_ON_DEMAND, // preload low-res on screen load - BGCACHE_FULL, - NUM_BackgroundCacheMode, - BackgroundCacheMode_Invalid -}; -*/ enum HighResolutionTextures { HighResolutionTextures_Auto, @@ -165,8 +154,7 @@ class PrefsManager Preference m_bPAL; Preference m_bDelayedTextureDelete; Preference m_bDelayedModelDelete; - Preference m_BannerCache; - //Preference m_BackgroundCache; + Preference m_ImageCache; Preference m_bFastLoad; Preference m_bFastLoadAdditionalSongs; Preference m_NeverCacheList; diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index bab3c4a248..ae0973d4dd 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -24,8 +24,7 @@ #include "Style.h" #include "PlayerState.h" #include "CommonMetrics.h" -#include "BannerCache.h" -//#include "BackgroundCache.h" +#include "ImageCache.h" #include "ScreenPrompt.h" #include "Song.h" #include "InputEventPlus.h" @@ -148,7 +147,7 @@ void ScreenSelectMusic::Init() m_TexturePreload.Load(m_sFallbackCDTitlePath); // load banners - if (PREFSMAN->m_BannerCache != BNCACHE_OFF) + if (PREFSMAN->m_ImageCache != IMGCACHE_OFF) { m_TexturePreload.Load(Banner::SongBannerTexture(THEME->GetPathG("Banner", "all music"))); m_TexturePreload.Load(Banner::SongBannerTexture(THEME->GetPathG("Common", "fallback banner"))); @@ -156,22 +155,9 @@ void ScreenSelectMusic::Init() m_TexturePreload.Load(Banner::SongBannerTexture(THEME->GetPathG("Banner", "random"))); m_TexturePreload.Load(Banner::SongBannerTexture(THEME->GetPathG("Banner", "mode"))); } - // load backgrounds - /* - if( PREFSMAN->m_BackgroundCache != BGCACHE_OFF ) - { - m_TexturePreload.Load( Sprite::SongBGTexture(THEME->GetPathG("SongBackgroundItem","AllMusic")) ); - m_TexturePreload.Load( Sprite::SongBGTexture(THEME->GetPathG("Common","fallback banner")) ); - m_TexturePreload.Load( Sprite::SongBGTexture(THEME->GetPathG("SongBackgroundItem","roulette")) ); - m_TexturePreload.Load( Sprite::SongBGTexture(THEME->GetPathG("SongBackgroundItem","random")) ); - m_TexturePreload.Load( Sprite::SongBGTexture(THEME->GetPathG("SongBackgroundItem","Mode")) ); - m_TexturePreload.Load( Sprite::SongBGTexture(THEME->GetPathG("SongBackgroundItem","group fallback")) ); - } - */ // Load low-res banners and backgrounds if needed. - BANNERCACHE->Demand(); - //BACKGROUNDCACHE->Demand(); + IMAGECACHE->Demand("Banner"); // build the playlist groups here, songmanager's init from disk can't because // profiles aren't loaded until after that's done -mina @@ -308,8 +294,7 @@ void ScreenSelectMusic::BeginScreen() ScreenSelectMusic::~ScreenSelectMusic() { LOG->Trace("ScreenSelectMusic::~ScreenSelectMusic()"); - BANNERCACHE->Undemand(); - //BACKGROUNDCACHE->Undemand(); + IMAGECACHE->Undemand("Banner"); } // If bForce is true, the next request will be started even if it might cause a skip. diff --git a/src/Song.cpp b/src/Song.cpp index c0418f0372..fdf01dcb8d 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -12,8 +12,7 @@ #include "Style.h" #include "FontCharAliases.h" #include "TitleSubstitution.h" -#include "BannerCache.h" -//#include "BackgroundCache.h" +#include "ImageCache.h" #include "Sprite.h" #include "RageFileManager.h" #include "RageSurface.h" @@ -35,6 +34,7 @@ #include "NotesWriterETT.h" #include "LyricsLoader.h" #include "ActorUtil.h" +#include "CommonMetrics.h" #include "GameState.h" #include @@ -89,6 +89,8 @@ Song::Song() m_bHasBanner = false; m_bHasBackground = false; m_loaded_from_autosave= false; + ImageDir.clear(); + split( CommonMetrics::IMAGES_TO_CACHE, ",", ImageDir ); } Song::~Song() @@ -396,14 +398,14 @@ bool Song::LoadFromSongDir( RString sDir, bool load_autosave ) (*s)->Compress(); } - // Load the cached banners, if it's not loaded already. - if( PREFSMAN->m_BannerCache == BNCACHE_LOW_RES_PRELOAD && m_bHasBanner ) - BANNERCACHE->LoadBanner( GetBannerPath() ); - // Load the cached background, if it's not loaded already. - /* - if( PREFSMAN->m_BackgroundCache == BGCACHE_LOW_RES_PRELOAD && m_bHasBackground ) - BACKGROUNDCACHE->LoadBackground( GetBackgroundPath() ); - */ + // Load the cached Images, if it's not loaded already. + if( PREFSMAN->m_ImageCache == IMGCACHE_LOW_RES_PRELOAD ) + { + for( std::string Image : ImageDir ) + { + IMAGECACHE->LoadImage( Image, GetCacheFile( Image ) ); + } + } if( !m_bHasMusic ) { @@ -618,13 +620,10 @@ void Song::TidyUpData( bool from_cache, bool /* duringCache */ ) m_bHasMusic = HasMusic(); m_bHasBanner = HasBanner(); m_bHasBackground = HasBackground(); - - if(m_bHasBanner) - { BANNERCACHE->CacheBanner(GetBannerPath()); } - /* - if(m_bHasBackground) - { BANNERCACHE->CacheBackground(GetBackgroundPath()); } - */ + for( std::string Image : ImageDir) + { + IMAGECACHE->LoadImage( Image, GetCacheFile( Image ) ); + } // There are several things that need to find a file from the dir with a // particular extension or type of extension. So fetch a list of all @@ -1370,6 +1369,73 @@ void Song::RemoveAutosave() } } +// We want to return a filename, We use this function for that. +std::string Song::GetCacheFile(std::string sType) +{ + // We put the Predefined images into a map. + map< std::string, std::string > PreDefs; + PreDefs["Banner"] = GetBannerPath(); + PreDefs["Background"] = GetBackgroundPath(); + PreDefs["CDTitle"] = GetCDTitlePath(); + PreDefs["Jacket"] = GetJacketPath(); + PreDefs["CDImage"] = GetCDImagePath(); + PreDefs["Disc"] = GetDiscPath(); + + // Check if Predefined images exist, And return function if they do. + if(PreDefs[sType.c_str()].c_str()) + return PreDefs[sType.c_str()].c_str(); + + // Get all image files and put them into a vector. + vector song_dir_listing; + FILEMAN->GetDirListing(m_sSongDir + "*", song_dir_listing, false, false); + vector image_list; + vector fill_exts = ActorUtil::GetTypeExtensionList(FT_Bitmap); + for( std::string Image : song_dir_listing ) + { + std::string FileExt = GetExtension(Image); + transform(FileExt.begin(), FileExt.end(), FileExt.begin(),::tolower); + for ( std::string FindExt : fill_exts ) + { + if(FileExt == FindExt) + image_list.push_back(Image); + } + } + + // Create a map that contains all the filenames to search for. + map > PreSets; + PreSets["Banner"][1] = "bn"; + PreSets["Banner"][2] = "banner"; + PreSets["Background"][1] = "bg"; + PreSets["Background"][2] = "background"; + PreSets["CDTitle"][1] = "cdtitle"; + PreSets["Jacket"][1] = "jk_"; + PreSets["Jacket"][2] = "jacket"; + PreSets["Jacket"][3] = "albumart"; + PreSets["CDImage"][1] = "-cd"; + PreSets["Disc"][1] = " disc"; + PreSets["Disc"][2] = " title"; + + for( std::string Image : image_list) + { + // We want to make it lower case. + transform(Image.begin(), Image.end(), Image.begin(),::tolower); + for( std::pair< const int, std::string> PreSet : PreSets[sType.c_str()] ) + { + // Search for image using PreSets. + size_t Found = Image.find(PreSet.second.c_str()); + if(Found!=std::string::npos) + return GetSongAssetPath( Image, m_sSongDir ); + } + // Search for the image directly if it doesnt exist in PreSets, + // Or incase we define our own stuff. + size_t Found = Image.find(sType.c_str()); + if(Found!=std::string::npos) + return GetSongAssetPath( Image, m_sSongDir ); + } + // Return empty if nothing found. + return ""; +} + RString Song::GetFileHash() { if (m_sFileHash.empty()) { diff --git a/src/Song.h b/src/Song.h index 720aab26fe..544c0e562d 100644 --- a/src/Song.h +++ b/src/Song.h @@ -248,6 +248,8 @@ class Song RString m_sCDTitleFile; RString m_sPreviewVidFile; + vector ImageDir; + static RString GetSongAssetPath( RString sPath, const RString &sSongPath ); RString GetMusicPath() const; RString GetInstrumentTrackPath( InstrumentTrack it ) const; @@ -261,6 +263,7 @@ class Song RString GetPreviewVidPath() const; RString GetPreviewMusicPath() const; float GetPreviewStartSeconds() const; + std::string GetCacheFile( std::string sPath ); // how have i not jammed anything here yet - mina diff --git a/src/SongCacheIndex.cpp b/src/SongCacheIndex.cpp index 8e2360249b..3119b69c50 100644 --- a/src/SongCacheIndex.cpp +++ b/src/SongCacheIndex.cpp @@ -6,6 +6,7 @@ #include "RageFileManager.h" #include "Song.h" #include "SpecialFiles.h" +#include "CommonMetrics.h" /* * A quick explanation of song cache hashes: Each song has two hashes; a hash of the @@ -90,10 +91,13 @@ void SongCacheIndex::ReadCacheIndex() LOG->Trace( "Cache format is out of date. Deleting all cache files." ); EmptyDir( SpecialFiles::CACHE_DIR ); - EmptyDir( SpecialFiles::CACHE_DIR+"Banners/" ); - //EmptyDir( SpecialFiles::CACHE_DIR+"Backgrounds/" ); EmptyDir( SpecialFiles::CACHE_DIR+"Songs/" ); EmptyDir( SpecialFiles::CACHE_DIR+"Courses/" ); + + vector ImageDir; + split( CommonMetrics::IMAGES_TO_CACHE, ",", ImageDir ); + for( std::string Image : ImageDir ) + EmptyDir( SpecialFiles::CACHE_DIR+Image+"/" ); CacheIndex.Clear(); /* This is right now in place because our song file paths are apparently being diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 368f0f6302..4e134c3cc7 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -4,7 +4,7 @@ #include "ActorUtil.h" #include "AnnouncerManager.h" #include "BackgroundUtil.h" -#include "BannerCache.h" +#include "ImageCache.h" #include "CommonMetrics.h" #include "Foreach.h" #include "GameManager.h" @@ -217,7 +217,7 @@ int SongManager::DifferentialReloadDir(string dir) { LOG->Trace("Differential load of %i songs from \"%s\"", loaded, (dir + sGroupDirName).c_str()); AddGroup(dir, sGroupDirName); - BANNERCACHE->CacheBanner(GetSongGroupBannerPath(sGroupDirName)); + IMAGECACHE->CacheImage("Banner",GetSongGroupBannerPath(sGroupDirName)); } return newsongs; } @@ -660,7 +660,7 @@ void SongManager::LoadStepManiaSongDir( RString sDir, LoadingWindow *ld ) AddGroup(sDir, sGroupDirName); // Cache and load the group banner. (and background if it has one -aj) - BANNERCACHE->CacheBanner( GetSongGroupBannerPath(sGroupDirName) ); + IMAGECACHE->CacheImage( "Banner", GetSongGroupBannerPath(sGroupDirName) ); } if( ld ) { @@ -670,7 +670,7 @@ void SongManager::LoadStepManiaSongDir( RString sDir, LoadingWindow *ld ) void SongManager::PreloadSongImages() { - if( PREFSMAN->m_BannerCache != BNCACHE_FULL ) + if( PREFSMAN->m_ImageCache != IMGCACHE_FULL ) return; /* Load textures before unloading old ones, so we don't reload textures diff --git a/src/Sprite.cpp b/src/Sprite.cpp index 2184f39bd2..f32cb3e2b6 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -15,6 +15,8 @@ #include "LuaBinding.h" #include "LuaManager.h" #include "InputFilter.h" +#include "ImageCache.h" +#include "ThemeMetric.h" REGISTER_ACTOR_CLASS( Sprite ); @@ -338,6 +340,27 @@ void Sprite::LoadFromTexture( const RageTextureID &ID ) SetTexture( pTexture ); } +void Sprite::LoadFromCached( const RString &sDir, const RString &sPath ) +{ + if( sPath.empty() ) + { + Load( THEME->GetPathG("Common","fallback %s", sDir) ); + return; + } + + RageTextureID ID; + + // Try to load the low quality version. + ID = IMAGECACHE->LoadCachedImage( sDir, sPath ); + + if( TEXTUREMAN->IsTextureRegistered(ID) ) + Load( ID ); + else if( IsAFile(sPath) ) + Load( sPath ); + else + Load( THEME->GetPathG("Common","fallback %s", sDir) ); +} + void Sprite::LoadStatesFromTexture() { // Assume the frames of this animation play in sequential order with 0.1 second delay. @@ -1248,12 +1271,18 @@ class LunaSprite: public Luna p->m_DecodeMovie= BArg(1); COMMON_RETURN_SELF; } + static int LoadFromCached( T* p, lua_State *L ) + { + p->LoadFromCached( SArg(1), SArg(2) ); + COMMON_RETURN_SELF; + } LunaSprite() { ADD_METHOD( Load ); ADD_METHOD( LoadBanner ); ADD_METHOD( LoadBackground ); + ADD_METHOD( LoadFromCached ); ADD_METHOD( customtexturerect ); ADD_METHOD( SetCustomImageRect ); ADD_METHOD( SetCustomPosCoords ); diff --git a/src/Sprite.h b/src/Sprite.h index a8b9679b54..b00a886a85 100644 --- a/src/Sprite.h +++ b/src/Sprite.h @@ -76,7 +76,8 @@ class Sprite: public Actor void StretchTexCoords( float fX, float fY ); void AddImageCoords( float fX, float fY ); // in image pixel space void SetEffectMode( EffectMode em ) { m_EffectMode = em; } - + + void LoadFromCached( const RString &sDir, const RString &sPath ); void SetTexCoordVelocity(float fVelX, float fVelY); /** * @brief Scale the Sprite while maintaining the aspect ratio. diff --git a/src/StepMania.cpp b/src/StepMania.cpp index 34883db700..ecfd4b4e86 100644 --- a/src/StepMania.cpp +++ b/src/StepMania.cpp @@ -54,13 +54,12 @@ #include "InputMapper.h" #include "InputQueue.h" #include "SongCacheIndex.h" -#include "BannerCache.h" +#include "ImageCache.h" #include "FilterManager.h" #if !defined(WITHOUT_NETWORKING) #include "DownloadManager.h" #endif #include "ScoreManager.h" -//#include "BackgroundCache.h" #include "RageFileManager.h" #include "ModelManager.h" #include "CryptManager.h" @@ -297,8 +296,7 @@ void ShutdownGame() SAFE_DELETE( CRYPTMAN ); SAFE_DELETE( MEMCARDMAN ); SAFE_DELETE( SONGMAN ); - SAFE_DELETE( BANNERCACHE ); - //SAFE_DELETE( BACKGROUNDCACHE ); + SAFE_DELETE( IMAGECACHE ); SAFE_DELETE( SONGINDEX ); SAFE_DELETE( SOUND ); // uses GAMESTATE, PREFSMAN SAFE_DELETE( PREFSMAN ); @@ -406,9 +404,7 @@ static void AdjustForChangedSystemCapabilities() /* Preloaded banners takes about 9k per song. Although it's smaller than the * actual song data, it still adds up with a lot of songs. * Disable it for 64-meg systems. */ - PREFSMAN->m_BannerCache.Set( LowMemory ? BNCACHE_OFF:BNCACHE_LOW_RES_PRELOAD ); - // might wanna do this for backgrounds, too... -aj - //PREFSMAN->m_BackgroundCache.Set( LowMemory ? BGCACHE_OFF:BGCACHE_LOW_RES_PRELOAD ); + PREFSMAN->m_ImageCache.Set( LowMemory ? IMGCACHE_OFF:IMGCACHE_LOW_RES_PRELOAD ); PREFSMAN->SavePrefsToDisk(); #endif @@ -1152,8 +1148,7 @@ int sm_main(int argc, char* argv[]) INPUTQUEUE = new InputQueue; SONGINDEX = new SongCacheIndex; - BANNERCACHE = new BannerCache; - //BACKGROUNDCACHE = new BackgroundCache; + IMAGECACHE = new ImageCache; // depends on SONGINDEX: SONGMAN = new SongManager;