From fefadeb5344f82098804cd71c3fdf8abaca6a1a4 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 27 Nov 2018 00:45:52 -0500 Subject: [PATCH] Solved the issue where a song located directly in the Songs folder would crash the game instantly, it now loads into a group called "Songs" fixes maybe set group for stray songs in the song folders as "Ungrouped Songs" also efficiency changes --- src/Player.cpp | 2 +- src/Song.cpp | 2 +- src/SongManager.cpp | 364 ++++++++++++++++++++++++-------------------- src/SongManager.h | 4 +- 4 files changed, 199 insertions(+), 173 deletions(-) diff --git a/src/Player.cpp b/src/Player.cpp index bfa9064480..e4d834fcbd 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -3523,7 +3523,7 @@ Player::RenderAllNotesIgnoreScores() // Find the tapnote we are on TapNote* pTN = NULL; NoteData::iterator iter = m_NoteData.FindTapNote(track, row); - DEBUG_ASSERT(iter != m_NoteData.end(col)); + DEBUG_ASSERT(iter != m_NoteData.end(track)); pTN = &iter->second; // Reset the score so it can be visible diff --git a/src/Song.cpp b/src/Song.cpp index 54cae5c6b9..a6820002bb 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -379,7 +379,7 @@ Song::FinalizeLoading() // save group name vector sDirectoryParts; split(m_sSongDir, "/", sDirectoryParts, false); - ASSERT(sDirectoryParts.size() >= 4); /* e.g. "/Songs/Slow/Taps/" */ + // ASSERT(sDirectoryParts.size() >= 4); /* e.g. "/Songs/Slow/Taps/" */ m_sGroupName = sDirectoryParts[sDirectoryParts.size() - 3]; // second from last item ASSERT(m_sGroupName != ""); diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 52ec6b778c..2a798e9556 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -37,6 +37,16 @@ #include "arch/LoadingWindow/LoadingWindow.h" #include "ScreenManager.h" +struct SongDir { + RString path; + SongDir(RString path) : path(path) {} +}; +struct Group { + RString name; + vector songs; + Group(RString name) : name(name) {} +}; + SongManager* SONGMAN = NULL; // global and accessible from anywhere in our program @@ -135,66 +145,74 @@ SongManager::DifferentialReload() int SongManager::DifferentialReloadDir(string dir) { - if (dir.substr(dir.size()) != "/") + if (dir.back() != '/') dir += "/"; int newsongs = 0; - vector arrayGroupDirs; - GetDirListing(dir + "*", arrayGroupDirs, true); - StripCvsAndSvn(arrayGroupDirs); - StripMacResourceForks(arrayGroupDirs); - SortRStringArray(arrayGroupDirs); + vector folders; + GetDirListing(dir + "*", folders, true); + StripCvsAndSvn(folders); + StripMacResourceForks(folders); + SortRStringArray(folders); - vector> arrayGroupSongDirs; + vector groups; + Group unknownGroup("Unknown Group"); int groupIndex, songCount, songIndex; groupIndex = 0; songCount = 0; - FOREACH_CONST(RString, arrayGroupDirs, s) - { - RString sGroupDirName = *s; - SanityCheckGroupDir(dir + sGroupDirName); - - vector arraySongDirs; - GetDirListing(dir + sGroupDirName + "/*", arraySongDirs, true, true); - StripCvsAndSvn(arraySongDirs); - StripMacResourceForks(arraySongDirs); - SortRStringArray(arraySongDirs); + for (const auto& folder : folders) { + if (IsSongDir(dir + folder)) { + songCount++; + unknownGroup.songs.emplace_back(SongDir(folder)); + } + else { + vector songdirs; + GetDirListing(dir + folder + "/*", songdirs, true, true); + StripCvsAndSvn(songdirs); + StripMacResourceForks(songdirs); + SortRStringArray(songdirs); + Group group(folder); + for (auto& song : songdirs) { + group.songs.emplace_back(SongDir(song)); + } - arrayGroupSongDirs.emplace_back(arraySongDirs); - songCount += arraySongDirs.size(); + groups.emplace_back(group); + songCount += group.songs.size(); + } } - + if (!unknownGroup.songs.empty()) { + groups.emplace_back(unknownGroup); + songCount += unknownGroup.songs.size(); + } + if (songCount == 0) return 0; groupIndex = 0; songIndex = 0; - FOREACH_CONST(RString, arrayGroupDirs, s) - { - RString sGroupDirName = *s; - vector& arraySongDirs = arrayGroupSongDirs[groupIndex++]; + for (auto& group : groups) { + vector& songDirs = group.songs; int loaded = 0; - SongPointerVector& index_entry = m_mapSongGroupIndex[sGroupDirName]; - RString group_base_name = Basename(sGroupDirName); - for (size_t j = 0; j < arraySongDirs.size(); ++j) { - RString sSongDirName = arraySongDirs[j]; - + SongPointerVector& index_entry = m_mapSongGroupIndex[group.name]; + RString group_base_name = Basename(group.name); + for (auto& songDir : songDirs) { // skip any dir we've already loaded -mina - RString hur = sSongDirName + "/"; + RString hur = songDir.path + "/"; hur.MakeLower(); if (m_SongsByDir.count(hur)) continue; Song* pNewSong = new Song; - if (!pNewSong->LoadFromSongDir(sSongDirName)) { + if (!pNewSong->LoadFromSongDir(songDir.path)) { delete pNewSong; continue; } - + if (group.name == "Unknown Group") + pNewSong->m_sGroupName = "Ungrouped Songs"; AddSongToList(pNewSong); AddKeyedPointers(pNewSong); @@ -202,7 +220,7 @@ SongManager::DifferentialReloadDir(string dir) Message msg("DFRUpdate"); msg.SetParam("txt", - "Loading:\n" + sGroupDirName + "\n" + + "Loading:\n" + group.name + "\n" + pNewSong->GetMainTitle()); MESSAGEMAN->Broadcast(msg); SCREENMAN->Draw(); // not sure if this needs to be handled better @@ -217,10 +235,10 @@ SongManager::DifferentialReloadDir(string dir) continue; LOG->Trace("Differential load of %i songs from \"%s\"", loaded, - (dir + sGroupDirName).c_str()); + (dir + group.name).c_str()); - AddGroup(dir, sGroupDirName); - IMAGECACHE->CacheImage("Banner", GetSongGroupBannerPath(sGroupDirName)); + AddGroup(dir, group.name); + IMAGECACHE->CacheImage("Banner", GetSongGroupBannerPath(dir + group.name)); } return newsongs; } @@ -235,14 +253,14 @@ split(vector& v, size_t elementsPerThread) { std::vector> ranges; if (elementsPerThread <= 0 || elementsPerThread >= v.size()) { - ranges.push_back(std::make_pair(v.begin(), v.end())); + ranges.emplace_back(std::make_pair(v.begin(), v.end())); return ranges; } size_t range_count = (v.size() + 1) / elementsPerThread + 1; size_t ePT = v.size() / range_count; if (ePT == 0) { - ranges.push_back(std::make_pair(v.begin(), v.end())); + ranges.emplace_back(std::make_pair(v.begin(), v.end())); return ranges; } size_t i; @@ -250,9 +268,9 @@ split(vector& v, size_t elementsPerThread) it b = v.begin(); for (i = 0; i < v.size() - ePT; i += ePT) - ranges.push_back(std::make_pair(b + i, b + i + ePT)); + ranges.emplace_back(std::make_pair(b + i, b + i + ePT)); - ranges.push_back(std::make_pair(b + i, v.end())); + ranges.emplace_back(std::make_pair(b + i, v.end())); return ranges; } @@ -633,25 +651,24 @@ static LocalizedString FOLDER_CONTAINS_MUSIC_FILES( "must " "reside in a group folder. For example, \"Songs/Originals/My " "Song\"."); -void -SongManager::SanityCheckGroupDir(const RString& sDir) const -{ - // Check to see if they put a song directly inside the group folder. - vector arrayFiles; - GetDirListing(sDir + "/*", arrayFiles); - const vector& audio_exts = - ActorUtil::GetTypeExtensionList(FT_Sound); - FOREACH(RString, arrayFiles, fname) - { - const RString ext = GetExtension(*fname); - FOREACH_CONST(RString, audio_exts, aud) +bool +SongManager::IsSongDir(const RString& sDir) +{ + // Check to see if they put a song directly inside the group folder. + vector arrayFiles; + GetDirListing(sDir + "/*", arrayFiles); + const vector& audio_exts = + ActorUtil::GetTypeExtensionList(FT_Sound); + for (auto& fname : arrayFiles) { - if (ext == *aud) { - RageException::Throw(FOLDER_CONTAINS_MUSIC_FILES.GetValue(), - sDir.c_str()); - } + const RString ext = GetExtension(fname); + for (auto& aud : audio_exts) { + if (ext == aud) { + return true; + } + } } - } + return false; } bool @@ -737,121 +754,130 @@ static LocalizedString LOADING_SONGS("SongManager", "Loading songs..."); void SongManager::LoadStepManiaSongDir(RString sDir, LoadingWindow* ld) { - vector arrayGroupDirs; - GetDirListing(sDir + "*", arrayGroupDirs, true); - StripCvsAndSvn(arrayGroupDirs); - StripMacResourceForks(arrayGroupDirs); - SortRStringArray(arrayGroupDirs); - vector> arrayGroupSongDirs; - int songCount = 0; - if (ld != nullptr) { - ld->SetIndeterminate(false); - ld->SetTotalWork(arrayGroupDirs.size()); - ld->SetText("Sanity checking groups"); - } - int groupsChecked = 0; - int onePercent = std::max(static_cast(arrayGroupDirs.size() / 100), 1); - FOREACH_CONST(RString, arrayGroupDirs, s) - { - RString sGroupDirName = *s; - SanityCheckGroupDir(sDir + sGroupDirName); - vector arraySongDirs; - GetDirListing(sDir + sGroupDirName + "/*", arraySongDirs, true, true); - StripCvsAndSvn(arraySongDirs); - StripMacResourceForks(arraySongDirs); - SortRStringArray(arraySongDirs); - arrayGroupSongDirs.emplace_back(arraySongDirs); - songCount += arraySongDirs.size(); - if (ld != nullptr && groupsChecked % onePercent == 0) - ld->SetProgress(++groupsChecked); - } - - if (ld != nullptr) { - ld->SetIndeterminate(false); - ld->SetTotalWork(arrayGroupDirs.size()); - ld->SetText("Loading Songs From Disk\n"); - ld->SetProgress(0); - } - int groupIndex = 0; - onePercent = std::max(static_cast(arrayGroupDirs.size() / 100), 1); - - function*>>, - vectorIt*>>>, - ThreadData*)> - callback = - [&sDir](std::pair*>>, - vectorIt*>>> workload, - ThreadData* data) { - auto pair = - static_cast*>(data->data); - auto onePercent = pair->first; - auto ld = pair->second; - int counter = 0; - int lastUpdate = 0; - for (auto it = workload.first; it != workload.second; it++) { - auto pair = *it; - auto& sGroupDirName = *(it->first); - counter++; - vector& arraySongDirs = *(it->second); - if (counter % onePercent == 0) { - data->_progress += counter - lastUpdate; - lastUpdate = counter; - data->setUpdated(true); + vector songFolders; + GetDirListing(sDir + "*", songFolders, true); + StripCvsAndSvn(songFolders); + StripMacResourceForks(songFolders); + SortRStringArray(songFolders); + int songCount = 0; + if (ld != nullptr) { + ld->SetIndeterminate(false); + ld->SetTotalWork(songFolders.size()); + ld->SetText("Checking song folders"); + } + vector groups; + auto unknownGroup = Group(RString("Unknown Group")); + int foldersChecked = 0; + int onePercent = std::max(static_cast(songFolders.size() / 100), 1); + for (const auto& folder : songFolders) + { + if (IsSongDir(sDir + folder)) { + auto s = SongDir(sDir + folder); + unknownGroup.songs.emplace_back(s); } - int loaded = 0; - SongPointerVector& index_entry = - SONGMAN->m_mapSongGroupIndex[sGroupDirName]; - RString group_base_name = Basename(sGroupDirName); - for (size_t j = 0; j < arraySongDirs.size(); ++j) { - RString sSongDirName = arraySongDirs[j]; - RString hur = sSongDirName + "/"; - hur.MakeLower(); - if (SONGMAN->m_SongsByDir.count(hur)) - continue; - Song* pNewSong = new Song; - if (!pNewSong->LoadFromSongDir(sSongDirName)) { - delete pNewSong; - continue; - } - { - std::lock_guard lk(diskLoadSongMutex); - SONGMAN->AddSongToList(pNewSong); - SONGMAN->AddKeyedPointers(pNewSong); - } - index_entry.emplace_back(pNewSong); - loaded++; + else { + vector songPaths; + auto group = Group(folder); + GetDirListing(sDir + folder + "/*", songPaths, true, true); + StripCvsAndSvn(songPaths); + StripMacResourceForks(songPaths); + SortRStringArray(songPaths); + for (auto& song : songPaths) { + group.songs.emplace_back(SongDir(song)); + } + songCount += group.songs.size(); + groups.emplace_back(group); + if (ld != nullptr && foldersChecked % onePercent == 0) + ld->SetProgress(++foldersChecked); } - if (!loaded) - continue; - LOG->Trace("Loaded %i songs from \"%s\"", - loaded, - (sDir + sGroupDirName).c_str()); - { - std::lock_guard lk(diskLoadGroupMutex); - SONGMAN->AddGroup(sDir, sGroupDirName); - IMAGECACHE->CacheImage( - "Banner", SONGMAN->GetSongGroupBannerPath(sGroupDirName)); + } + if (!unknownGroup.songs.empty()) groups.emplace_back(unknownGroup); + + if (ld != nullptr) { + ld->SetIndeterminate(false); + ld->SetTotalWork(groups.size()); + ld->SetText("Loading Songs From Disk\n"); + ld->SetProgress(0); + } + int groupIndex = 0; + onePercent = std::max(static_cast(groups.size() / 100), 1); + + auto callback = + [&sDir](std::pair, + vectorIt> workload, + ThreadData* data) { + auto pair = + static_cast*>(data->data); + auto onePercent = pair->first; + auto ld = pair->second; + int counter = 0; + int lastUpdate = 0; + for (auto it = workload.first; it != workload.second; it++) { + auto pair = *it; + auto& sGroupName = it->name; + counter++; + vector& arraySongDirs = it->songs; + if (counter % onePercent == 0) { + data->_progress += counter - lastUpdate; + lastUpdate = counter; + data->setUpdated(true); + } + int loaded = 0; + SongPointerVector& index_entry = + SONGMAN->m_mapSongGroupIndex[sGroupName]; + RString group_base_name = sGroupName; + for (auto sSongDirName : arraySongDirs) { + RString hur = sSongDirName.path + "/"; + hur.MakeLower(); + if (SONGMAN->m_SongsByDir.count(hur)) + continue; + Song* pNewSong = new Song; + if (!pNewSong->LoadFromSongDir(sSongDirName.path)) { + delete pNewSong; + continue; + } + if (sGroupName == "Unknown Group") + pNewSong->m_sGroupName = "Ungrouped Songs"; + { + std::lock_guard lk(diskLoadSongMutex); + SONGMAN->AddSongToList(pNewSong); + SONGMAN->AddKeyedPointers(pNewSong); + } + index_entry.emplace_back(pNewSong); + loaded++; + } + if (!loaded) + continue; + LOG->Trace("Loaded %i songs from \"%s\"", + loaded, + (sDir + sGroupName).c_str()); + { + std::lock_guard lk(diskLoadGroupMutex); + SONGMAN->AddGroup(sDir, sGroupName); + IMAGECACHE->CacheImage( + "Banner", SONGMAN->GetSongGroupBannerPath(sDir + sGroupName)); + } } - } }; - auto onUpdate = [ld](int progress) { - if (ld) - ld->SetProgress(progress); - }; - vector*>> workload; - for (int i = 0; i < (int)arrayGroupDirs.size(); i++) { - workload.emplace_back( - make_pair(&arrayGroupDirs[i], &arrayGroupSongDirs[i])); - } - parallelExecution*>>( - workload, - onUpdate, - callback, - (void*)new pair(onePercent, ld)); + auto onUpdate = [ld](int progress) { + if (ld != nullptr) + ld->SetProgress(progress); + }; + vector workload; + for (auto& group : groups) { + workload.emplace_back(group); + } - if (ld != nullptr) { - ld->SetIndeterminate(true); - } + if (!workload.empty()) + parallelExecution( + workload, + onUpdate, + callback, + (void*)new pair(onePercent, ld)); + + if (ld != nullptr) { + ld->SetIndeterminate(true); + } } void @@ -1024,9 +1050,9 @@ SongManager::GetSongGroupColor(const RString& sSongGroup, } } - ASSERT_M(0, + /*ASSERT_M(0, ssprintf("requested color for song group '%s' that doesn't exist", - sSongGroup.c_str())); + sSongGroup.c_str()));*/ return RageColor(1, 1, 1, 1); } diff --git a/src/SongManager.h b/src/SongManager.h index fe94c5e7eb..cc5978f3d2 100644 --- a/src/SongManager.h +++ b/src/SongManager.h @@ -1,4 +1,4 @@ -#ifndef SONGMANAGER_H +#ifndef SONGMANAGER_H #define SONGMANAGER_H class LoadingWindow; @@ -171,7 +171,7 @@ class SongManager protected: void LoadStepManiaSongDir(RString sDir, LoadingWindow* ld); void LoadDWISongDir(const RString& sDir); - void SanityCheckGroupDir(const RString& sDir) const; + bool IsSongDir(const RString& sDir); bool AddGroup(const RString& sDir, const RString& sGroupDirName); void AddSongToList(Song* new_song);