From eddc5b2178806c30f8ed4b5915727fdfe4f5b906 Mon Sep 17 00:00:00 2001 From: theropfather Date: Wed, 3 Jan 2024 20:24:56 +0000 Subject: [PATCH 1/7] Re-add song deletion Re-add the old function and the prompt to trigger it --- .../Screen/Others/ScreenSelectMusic.cpp | 66 +++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/src/Etterna/Screen/Others/ScreenSelectMusic.cpp b/src/Etterna/Screen/Others/ScreenSelectMusic.cpp index 3a96c4d992..a92e873936 100644 --- a/src/Etterna/Screen/Others/ScreenSelectMusic.cpp +++ b/src/Etterna/Screen/Others/ScreenSelectMusic.cpp @@ -37,6 +37,10 @@ #include "Etterna/Actor/Gameplay/Player.h" #include "Etterna/Models/NoteData/NoteDataUtil.h" #include "Etterna/Singletons/ReplayManager.h" +#include "Etterna/Screen/Others/ScreenPrompt.h" +#include + +#include #include @@ -56,6 +60,7 @@ AutoScreenMessage(SM_SongChanged); AutoScreenMessage(SM_SortOrderChanging); AutoScreenMessage(SM_SortOrderChanged); AutoScreenMessage(SM_BackFromPlayerOptions); +AutoScreenMessage(SM_ConfirmDeleteSong); AutoScreenMessage(SM_BackFromNamePlaylist); AutoScreenMessage(SM_BackFromCalcTestStuff); @@ -387,10 +392,10 @@ void ScreenSelectMusic::DifferentialReload() { // reload songs - SONGMAN->DifferentialReload(); - + SONGMAN->DifferentialReload(); + if (IsTransitioning() || m_SelectionState == SelectionState_Finalized) { - return; + return; } const auto selSong = GAMESTATE->m_pCurSong; @@ -473,6 +478,24 @@ ScreenSelectMusic::Input(const InputEventPlus& input) m_MusicWheel.IsSettled() && input.type == IET_FIRST_PRESS) { if (ReloadCurrentSong()) return true; + } else if (input.DeviceI.device == DEVICE_KEYBOARD && bHoldingCtrl && + input.DeviceI.button == KEY_BACK && + input.type == IET_FIRST_PRESS && m_MusicWheel.IsSettled()) { + + // Keyboard shortcut to delete a song from disk (ctrl + backspace) + Song* songToDelete = m_MusicWheel.GetSelectedSong(); + + if (songToDelete && PREFSMAN->m_bAllowSongDeletion.Get()) { + m_pSongAwaitingDeletionConfirmation = songToDelete; + + ScreenPrompt::Prompt( + SM_ConfirmDeleteSong, + ssprintf(PERMANENTLY_DELETE.GetValue(), + songToDelete->m_sMainTitle.c_str(), + songToDelete->GetSongDir().c_str()), + PROMPT_YES_NO); + return true; + } } else if (holding_shift && bHoldingCtrl && c == 'P' && m_MusicWheel.IsSettled() && input.type == IET_FIRST_PRESS) { if (ReloadCurrentPack()) @@ -978,7 +1001,16 @@ ScreenSelectMusic::HandleScreenMessage(const ScreenMessage& SM) CodeDetector::RefreshCacheItems(CODES); } else if (SM == SM_LoseFocus) { CodeDetector::RefreshCacheItems(); // reset for other screens - } else if (SM == SM_BackFromCalcTestStuff) { + } else if (SM == SM_ConfirmDeleteSong) { + if (ScreenPrompt::s_LastAnswer == ANSWER_YES) { + OnConfirmSongDeletion(); + } else { + // need to resume the song preview that was automatically paused + m_MusicWheel.ChangeMusic(0); + } + } + else if (SM == SM_BackFromCalcTestStuff) + { auto ans = ScreenTextEntry::s_sLastAnswer; std::vector words; std::istringstream iss(ans); @@ -1103,6 +1135,32 @@ ScreenSelectMusic::HandleScreenMessage(const ScreenMessage& SM) ScreenWithMenuElements::HandleScreenMessage(SM); } +void +ScreenSelectMusic::OnConfirmSongDeletion() +{ + Song* deletedSong = m_pSongAwaitingDeletionConfirmation; + if (!deletedSong) { + //Locator::getLogger()->warn("Attempted to delete a null song (ScreenSelectMusic::OnConfirmSongDeletion)"); + return; + } + + /* TODO: Make this platform independent */ + const ghc::filesystem::path exeLocation = Core::Platform::getExecutableDirectory(); + const std::string prefix = exeLocation.parent_path(); + const std::filesystem::path songDir = std::filesystem::u8path(prefix + deletedSong->GetSongDir()); + + + // flush the deleted song from any caches + SONGMAN->UnlistSong(deletedSong); + // refresh the song list + m_MusicWheel.ReloadSongList(false, ""); + //Locator::getLogger()->trace("Deleting song: ", songDir.c_str()); + // delete the song directory from disk + + std::filesystem::remove_all(songDir); + m_pSongAwaitingDeletionConfirmation = NULL; +} + bool ScreenSelectMusic::MenuStart(const InputEventPlus& input) { From e41566e3668f01413e102249fb2d59ca039a2c82 Mon Sep 17 00:00:00 2001 From: theropfather Date: Wed, 3 Jan 2024 20:25:11 +0000 Subject: [PATCH 2/7] Add needed signatures --- src/Etterna/Screen/Others/ScreenSelectMusic.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Etterna/Screen/Others/ScreenSelectMusic.h b/src/Etterna/Screen/Others/ScreenSelectMusic.h index f7f5e96b38..94676572b8 100644 --- a/src/Etterna/Screen/Others/ScreenSelectMusic.h +++ b/src/Etterna/Screen/Others/ScreenSelectMusic.h @@ -86,6 +86,9 @@ class ScreenSelectMusic : public ScreenWithMenuElements void SwitchToPreferredDifficulty(); void AfterMusicChange(); + Song* m_pSongAwaitingDeletionConfirmation; + void OnConfirmSongDeletion(); + void CheckBackgroundRequests(bool bForce); bool DetectCodes(const InputEventPlus& input); From 7361be0c5bfa3fecf927f2316243b9ec16d29d20 Mon Sep 17 00:00:00 2001 From: theropfather Date: Wed, 3 Jan 2024 20:25:17 +0000 Subject: [PATCH 3/7] Add preference --- src/Etterna/Singletons/PrefsManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Etterna/Singletons/PrefsManager.cpp b/src/Etterna/Singletons/PrefsManager.cpp index 0c0b19f61f..fe6b50cd56 100644 --- a/src/Etterna/Singletons/PrefsManager.cpp +++ b/src/Etterna/Singletons/PrefsManager.cpp @@ -209,6 +209,7 @@ PrefsManager::PrefsManager() , m_logging_level("LoggingLevel", 2) , m_bEnableScoreboard("EnableScoreboard", true) , m_bEnableCrashUpload("EnableMinidumpUpload", false) + , m_bAllowSongDeletion("AllowSongDeletion", false) , m_bShowMinidumpUploadDialogue("ShowMinidumpUploadDialogue", true) { From 86a68651a2b1d623caecf5404148ebfcb7407382 Mon Sep 17 00:00:00 2001 From: theropfather Date: Wed, 3 Jan 2024 20:25:27 +0000 Subject: [PATCH 4/7] Define preference sig --- src/Etterna/Singletons/PrefsManager.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Etterna/Singletons/PrefsManager.h b/src/Etterna/Singletons/PrefsManager.h index ff4ec4b5f0..ec7c8264fb 100644 --- a/src/Etterna/Singletons/PrefsManager.h +++ b/src/Etterna/Singletons/PrefsManager.h @@ -241,6 +241,8 @@ class PrefsManager Preference m_bEnableCrashUpload; Preference m_bShowMinidumpUploadDialogue; + Preference m_bAllowSongDeletion; + void ReadPrefsFromIni(const IniFile& ini, const std::string& sSection, bool bIsStatic); From 2a6e503b2f405f7004fc2992a01cfb909e02798e Mon Sep 17 00:00:00 2001 From: theropfather Date: Wed, 3 Jan 2024 20:25:43 +0000 Subject: [PATCH 5/7] Re-add functions back to songmanager --- src/Etterna/Singletons/SongManager.cpp | 28 ++++++++++++++++++++++++++ src/Etterna/Singletons/SongManager.h | 6 ++++++ 2 files changed, 34 insertions(+) diff --git a/src/Etterna/Singletons/SongManager.cpp b/src/Etterna/Singletons/SongManager.cpp index ade1a954f3..09b9a5829e 100644 --- a/src/Etterna/Singletons/SongManager.cpp +++ b/src/Etterna/Singletons/SongManager.cpp @@ -974,6 +974,11 @@ SongManager::FreeSongs() m_pSongs.clear(); m_SongsByDir.clear(); + // also free the songs that have been deleted from disk + for (unsigned i = 0; i < m_pDeletedSongs.size(); ++i) + SAFE_DELETE(m_pDeletedSongs[i]); + m_pDeletedSongs.clear(); + m_mapSongGroupIndex.clear(); m_sSongGroupBannerPaths.clear(); @@ -984,6 +989,29 @@ SongManager::FreeSongs() m_pPopularSongs.clear(); } +void +SongManager::UnlistSong(Song* song) +{ + // cannot immediately free song data, as it is needed temporarily + // for smooth audio transitions, etc. Instead, remove it from the + // m_pSongs list and store it in a special place where it can safely + // be deleted later. + m_pDeletedSongs.emplace_back(song); + + // remove all occurences of the song in each of our song vectors + vector* songVectors[2] = { &m_pSongs, + &m_pPopularSongs}; + for (int songVecIdx = 0; songVecIdx < 2; ++songVecIdx) { + vector& v = *songVectors[songVecIdx]; + for (size_t i = 0; i < v.size(); ++i) { + if (v[i] == song) { + v.erase(v.begin() + i); + --i; + } + } + } +} + auto SongManager::IsGroupNeverCached(const std::string& group) const -> bool { diff --git a/src/Etterna/Singletons/SongManager.h b/src/Etterna/Singletons/SongManager.h index 2e515466a4..895fe7f00a 100644 --- a/src/Etterna/Singletons/SongManager.h +++ b/src/Etterna/Singletons/SongManager.h @@ -36,6 +36,9 @@ class SongManager void FreeSongs(); void Cleanup(); + void UnlistSong(Song* song); + + void Invalidate(const Song* pStaleSong); static auto GetPlaylists() -> std::map&; static void SaveEnabledSongsToPref(); @@ -179,6 +182,9 @@ class SongManager std::set m_GroupsToNeverCache; /** @brief The most popular songs ranked by number of plays. */ + + std::vector m_pDeletedSongs; + std::vector m_pPopularSongs; std::vector m_sSongGroupNames; From 905caab31f055b32978f516092b9e6cf04124571 Mon Sep 17 00:00:00 2001 From: theropfather Date: Wed, 3 Jan 2024 20:26:27 +0000 Subject: [PATCH 6/7] Update metrics for song deletion --- Themes/_fallback/metrics.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 43074fbfc4..0fa5cd6b5d 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -2215,7 +2215,7 @@ LineGO="lua,GlobalOffsetSeconds()" Fallback="ScreenOptionsServiceChild" NextScreen="ScreenOptionsService" PrevScreen="ScreenOptionsService" -LineNames="3,4,SI,SM,HN,SSR,14,30,OsuLifts,ReplayMods,PR,PackProgress,MinidumpUpload" +LineNames="3,4,SI,SM,HN,SSR,14,30,OsuLifts,ReplayMods,PR,PackProgress,MinidumpUpload,AllowSongDeletion" #LineScore="lua,UserPrefScoringMode()" Line3="lua,JudgeDifficulty()" Line4="conf,LifeDifficulty" @@ -2225,6 +2225,7 @@ LineHN="conf,MinTNSToHideNotes" LineSSR="conf,SortBySSRNormPercent" Line14="conf,EasterEggs" Line30="conf,FastLoad" +LineAllowSongDeletion="conf,AllowSongDeletion" #Line31="conf,FastLoadAdditionalSongs" LinePR="conf,EnablePitchRates" LineOsuLifts="conf,LiftsOnOsuHolds" From ab338cbb7d9a25b030bc06f8bf13e8e0a9d6552b Mon Sep 17 00:00:00 2001 From: theropfather Date: Wed, 3 Jan 2024 20:26:35 +0000 Subject: [PATCH 7/7] Add master? pref --- src/Etterna/Screen/Options/ScreenOptionsMasterPrefs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Etterna/Screen/Options/ScreenOptionsMasterPrefs.cpp b/src/Etterna/Screen/Options/ScreenOptionsMasterPrefs.cpp index 211e2b60fd..7ccce47350 100644 --- a/src/Etterna/Screen/Options/ScreenOptionsMasterPrefs.cpp +++ b/src/Etterna/Screen/Options/ScreenOptionsMasterPrefs.cpp @@ -827,6 +827,8 @@ InitializeConfOptions() ADD(ConfOption("PackProgressInWheel", MovePref, "Off", "On")); ADD(ConfOption("EnableMinidumpUpload", MovePref, "Off", "On")); + ADD(ConfOption("AllowSongDeletion", MovePref, "Off", "On")); + // Machine options ADD(ConfOption("TimingWindowScale", TimingWindowScale,