From f60707b5060e4645f0c302df26b7ef41a2315d6b Mon Sep 17 00:00:00 2001 From: Martin Natano Date: Thu, 9 Jun 2022 15:31:29 +0200 Subject: [PATCH] Add support for incremental updates to ScreenReloadSongs --- Themes/_fallback/metrics.ini | 1 + src/CourseUtil.h | 1 + src/ScreenInstallOverlay.cpp | 2 +- src/ScreenReloadSongs.cpp | 10 +++++- src/SongManager.cpp | 64 +++++++++++++++++++++++++++++------- src/SongManager.h | 47 ++++++++++++++++++++------ src/StepMania.cpp | 2 +- 7 files changed, 103 insertions(+), 24 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 8d9f1ce701..6e650f8e27 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -3241,6 +3241,7 @@ TimerOnCommand=visible,false Class="ScreenReloadSongs" Fallback="Screen" NextScreen=Branch.TitleMenu() +OnlyLoadAdditions=false [ScreenPlayerOptions] Fallback="ScreenOptions" diff --git a/src/CourseUtil.h b/src/CourseUtil.h index e681f918b5..fd01956a11 100644 --- a/src/CourseUtil.h +++ b/src/CourseUtil.h @@ -85,6 +85,7 @@ public: XNode* CreateNode() const; void LoadFromNode( const XNode* pNode ); + void FromPath( RString _sPath ) { sPath = _sPath; } RString ToString() const; bool IsValid() const; diff --git a/src/ScreenInstallOverlay.cpp b/src/ScreenInstallOverlay.cpp index d988b439b8..a8b4f0b7c9 100644 --- a/src/ScreenInstallOverlay.cpp +++ b/src/ScreenInstallOverlay.cpp @@ -177,7 +177,7 @@ void ScreenInstallOverlay::Update( float fDeltaTime ) playAfterLaunchInfo.OverlayWith( pali2 ); } if( playAfterLaunchInfo.bAnySongChanged ) - SONGMAN->Reload( nullptr ); + SONGMAN->Reload(); if( !playAfterLaunchInfo.sSongDir.empty() ) { diff --git a/src/ScreenReloadSongs.cpp b/src/ScreenReloadSongs.cpp index 0b6dbfe63a..0578288a2b 100644 --- a/src/ScreenReloadSongs.cpp +++ b/src/ScreenReloadSongs.cpp @@ -77,7 +77,15 @@ void ScreenReloadSongs::Update( float fDeltaTime ) ASSERT( !IsFirstUpdate() ); - SONGMAN->Reload( m_pLoadingWindow ); + bool onlyLoadAdditions = THEME->GetMetricB(m_sName, "OnlyLoadAdditions"); + if (onlyLoadAdditions) + { + SONGMAN->LoadAdditions( m_pLoadingWindow ); + } + else + { + SONGMAN->Reload( m_pLoadingWindow ); + } SCREENMAN->PostMessageToTopScreen( SM_GoToNextScreen, 0 ); } diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 11944d7b65..8bcf7dd405 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -93,7 +93,7 @@ SongManager::~SongManager() FreeSongs(); } -void SongManager::InitAll( LoadingWindow *ld ) +void SongManager::InitAll( LoadingWindow *ld, bool onlyAdditions ) { vector never_cache; split(PREFSMAN->m_NeverCacheList, ",", never_cache); @@ -102,8 +102,12 @@ void SongManager::InitAll( LoadingWindow *ld ) { m_GroupsToNeverCache.insert(*group); } - InitSongsFromDisk( ld ); - InitCoursesFromDisk( ld ); + InitSongsFromDisk( ld, onlyAdditions ); + InitCoursesFromDisk( ld, onlyAdditions ); + if (onlyAdditions) + { + DeleteAutogenCourses(); + } InitAutogenCourses(); InitRandomAttacks(); } @@ -168,7 +172,7 @@ void SongManager::Reload( LoadingWindow *ld ) FreeSongs(); - InitAll( ld ); + InitAll( ld, /*onlyAdditions=*/false ); // reload scores and unlocks afterward PROFILEMAN->LoadMachineProfile(); @@ -202,17 +206,30 @@ void SongManager::Reload( LoadingWindow *ld ) UpdatePreferredSort(); } -void SongManager::InitSongsFromDisk( LoadingWindow *ld ) +void SongManager::LoadAdditions( LoadingWindow *ld ) +{ + FILEMAN->FlushDirCache( SpecialFiles::SONGS_DIR ); + FILEMAN->FlushDirCache( SpecialFiles::COURSES_DIR ); + FILEMAN->FlushDirCache( EDIT_SUBDIR ); + + InitAll( ld, /*onlyAdditions=*/true ); + + UNLOCKMAN->Reload(); + + UpdatePreferredSort(); +} + +void SongManager::InitSongsFromDisk( LoadingWindow *ld, bool onlyAdditions ) { RageTimer tm; // Tell SONGINDEX to not write the cache index file every time a song adds // an entry. -Kyz SONGINDEX->delay_save_cache = true; IMAGECACHE->delay_save_cache = true; - LoadStepManiaSongDir( SpecialFiles::SONGS_DIR, ld ); + LoadSongDir( SpecialFiles::SONGS_DIR, ld, onlyAdditions ); LoadEnabledSongsFromPref(); SONGINDEX->SaveCacheIndex(); - SONGINDEX->delay_save_cache= false; + SONGINDEX->delay_save_cache = false; IMAGECACHE->WriteToDisk(); IMAGECACHE->delay_save_cache = false; @@ -312,8 +329,11 @@ void SongManager::AddGroup( RString sDir, RString sGroupDirName ) } static LocalizedString LOADING_SONGS ( "SongManager", "Loading songs..." ); -void SongManager::LoadStepManiaSongDir( RString sDir, LoadingWindow *ld ) +void SongManager::LoadSongDir( RString sDir, LoadingWindow *ld, bool onlyAdditions ) { + if( ld ) + ld->SetText( LOADING_SONGS ); + // Compositors and other stuff can impose some overhead on updating the // loading window, which slows down startup time for some people. // loading_window_last_update_time provides a timer so the loading window @@ -389,6 +409,15 @@ void SongManager::LoadStepManiaSongDir( RString sDir, LoadingWindow *ld ) { RString sSongDirName = arraySongDirs[j]; + // Skip already loaded songs if onlyAdditions is set. + if (onlyAdditions) + { + SongID songID; + songID.FromString(sSongDirName); + if (songID.ToSong() != nullptr) + continue; + } + // this is a song directory. Load a new song. if(ld && loading_window_last_update_time.Ago() > next_loading_window_update) { @@ -401,6 +430,7 @@ void SongManager::LoadStepManiaSongDir( RString sDir, LoadingWindow *ld ) ) ); } + Song* pNewSong = new Song; if( !pNewSong->LoadFromSongDir( sSongDirName ) ) { @@ -754,9 +784,9 @@ void SongManager::ResetGroupColors() COURSE_GROUP_COLOR.Clear(); NUM_SONG_GROUP_COLORS .Load( "SongManager", "NumSongGroupColors" ); - SONG_GROUP_COLOR .Load( "SongManager", SONG_GROUP_COLOR_NAME, NUM_SONG_GROUP_COLORS ); + SONG_GROUP_COLOR .Load( "SongManager", SONG_GROUP_COLOR_NAME, NUM_SONG_GROUP_COLORS ); NUM_COURSE_GROUP_COLORS .Load( "SongManager", "NumCourseGroupColors" ); - COURSE_GROUP_COLOR .Load( "SongManager", COURSE_GROUP_COLOR_NAME, NUM_COURSE_GROUP_COLORS ); + COURSE_GROUP_COLOR .Load( "SongManager", COURSE_GROUP_COLOR_NAME, NUM_COURSE_GROUP_COLORS ); } const vector &SongManager::GetSongs( const RString &sGroupName ) const @@ -869,9 +899,12 @@ RString SongManager::ShortenGroupName( RString sLongGroupName ) } static LocalizedString LOADING_COURSES ( "SongManager", "Loading courses..." ); -void SongManager::InitCoursesFromDisk( LoadingWindow *ld ) +void SongManager::InitCoursesFromDisk( LoadingWindow *ld, bool onlyAdditions ) { LOG->Trace( "Loading courses." ); + if( ld ) + ld->SetText( LOADING_COURSES ); + RageTimer loading_window_last_update_time; loading_window_last_update_time.Touch(); @@ -902,6 +935,15 @@ void SongManager::InitCoursesFromDisk( LoadingWindow *ld ) RString base_course_group= Basename(sCourseGroup); for (RString const &sCoursePath : vsCoursePaths) { + // Skip already loaded courses if onlyAdditions is set. + if (onlyAdditions) + { + CourseID courseID; + courseID.FromPath(sCoursePath); + if (courseID.ToCourse() != nullptr) + continue; + } + if(ld && loading_window_last_update_time.Ago() > next_loading_window_update) { loading_window_last_update_time.Touch(); diff --git a/src/SongManager.h b/src/SongManager.h index ee0e9bf62c..f9ac6fba4c 100644 --- a/src/SongManager.h +++ b/src/SongManager.h @@ -35,7 +35,13 @@ public: SongManager(); ~SongManager(); - void InitSongsFromDisk( LoadingWindow *ld ); + /** + * @brief Initialize all songs from disk + * @param ld the loading window to be updated, or nullptr + * @param onlyAdditions only load songs added after the last + * invocation of this function + */ + void InitSongsFromDisk( LoadingWindow *ld, bool onlyAdditions ); void FreeSongs(); void UnlistSong(Song *song); void Cleanup(); @@ -54,7 +60,13 @@ public: void LoadGroupSymLinks( RString sDir, RString sGroupFolder ); - void InitCoursesFromDisk( LoadingWindow *ld ); + /** + * @brief Initialize all courses from disk + * @param ld the loading window to be updated, or nullptr + * @param onlyAdditions only load courses added after the last + * invocation of this function + */ + void InitCoursesFromDisk( LoadingWindow *ld, bool onlyAdditions ); void InitAutogenCourses(); void InitRandomAttacks(); void FreeCourses(); @@ -64,8 +76,16 @@ public: void DeleteAutogenCourses(); void InvalidateCachedTrails(); - void InitAll( LoadingWindow *ld ); // songs, courses, groups - everything. - void Reload( LoadingWindow *ld=nullptr ); // songs, courses, groups - everything. + /** + * @brief Initialize all songs and courses from disk, and update + * autogenerated courses afterwards + * @param ld the loading window to be updated, or nullptr + * @param onlyAdditions only load songs and courses added after the + * last invocation of this function + */ + void InitAll( LoadingWindow *ld, bool onlyAdditions ); + void Reload( LoadingWindow *ld=nullptr ); + void LoadAdditions( LoadingWindow *ld=nullptr ); void PreloadSongImages(); bool IsGroupNeverCached(const RString& group) const; @@ -169,8 +189,14 @@ public: void PushSelf( lua_State *L ); protected: - void LoadStepManiaSongDir( RString sDir, LoadingWindow *ld ); - void LoadDWISongDir( RString sDir ); + /** + * @brief Load all songs from a directory + * @param sDir the directory to be loaded + * @param ld the loading window to be updated, or nullptr + * @param onlyAdditions only load songs added after the last + * invocation of this function + */ + void LoadSongDir( RString sDir, LoadingWindow *ld, bool onlyAdditions ); bool GetExtraStageInfoFromCourse( bool bExtra2, RString sPreferredGroup, Song*& pSongOut, Steps*& pStepsOut, StepsType stype ); void SanityCheckGroupDir( RString sDir ) const; void AddGroup( RString sDir, RString sGroupDirName ); @@ -181,12 +207,13 @@ protected: vector m_pSongs; map m_SongsByDir; set m_GroupsToNeverCache; + /** @brief Hold pointers to all the songs that have been deleted from disk but must at least be kept temporarily alive for smooth audio transitions. */ - vector m_pDeletedSongs; + vector m_pDeletedSongs; + /** @brief The most popular songs ranked by number of plays. */ - vector m_pPopularSongs; - //vector m_pRecentSongs; // songs recently played on the machine - vector m_pShuffledSongs; // used by GetRandomSong + vector m_pPopularSongs; + vector m_pShuffledSongs; // used by GetRandomSong struct PreferredSortSection { RString sName; diff --git a/src/StepMania.cpp b/src/StepMania.cpp index 36861420bf..34ceb0dff6 100644 --- a/src/StepMania.cpp +++ b/src/StepMania.cpp @@ -1123,7 +1123,7 @@ int sm_main(int argc, char* argv[]) // depends on SONGINDEX: SONGMAN = new SongManager; - SONGMAN->InitAll( pLoadingWindow ); // this takes a long time + SONGMAN->InitAll( pLoadingWindow, /*onlyAdditions=*/false ); // this takes a long time CRYPTMAN = new CryptManager; // need to do this before ProfileMan if( PREFSMAN->m_bSignProfileData ) CRYPTMAN->GenerateGlobalKeys();