diff --git a/include/UI/ViewControllers/SongList.hpp b/include/UI/ViewControllers/SongList.hpp index a0fc745..13aa492 100644 --- a/include/UI/ViewControllers/SongList.hpp +++ b/include/UI/ViewControllers/SongList.hpp @@ -156,7 +156,7 @@ DECLARE_CLASS_CODEGEN_INTERFACES(BetterSongSearch::UI::ViewControllers, SongList void SortAndFilterSongs(FilterTypes::SortMode sort, std::string_view search, bool resetTable); void ResetTable(); - SongDetailsCache::Song const* currentSong = nullptr; + void UpdateDetails(); void SetIsDownloaded(bool isDownloaded, bool downloadable = true); @@ -175,4 +175,11 @@ DECLARE_CLASS_CODEGEN_INTERFACES(BetterSongSearch::UI::ViewControllers, SongList void SongDataError(std::string message); void PlayerDataLoaded(); void OnSongsLoaded(std::span songs); + + SongDetailsCache::Song const* GetCurrentSong(); + void SetCurrentSong(SongDetailsCache::Song const* song); + + private: + std::shared_mutex _currentSongMutex; + SongDetailsCache::Song const* _currentSong = nullptr; }; diff --git a/src/UI/Manager.cpp b/src/UI/Manager.cpp index a8da6ba..1a428ea 100644 --- a/src/UI/Manager.cpp +++ b/src/UI/Manager.cpp @@ -73,7 +73,8 @@ custom_types::Helpers::Coroutine BetterSongSearch::UI::Manager::Debug() { auto songlist = fcInstance->SongListController; co_yield reinterpret_cast(UnityEngine::WaitForSeconds::New_ctor(0.1f)); songlist->SelectRandom(); - if (songlist->currentSong) { + auto currentSong = songlist->GetCurrentSong(); + if (currentSong) { co_yield reinterpret_cast(UnityEngine::WaitForSeconds::New_ctor(0.1f)); songlist->ShowSongDetails(); co_yield reinterpret_cast(UnityEngine::WaitForSeconds::New_ctor(0.1f)); diff --git a/src/UI/ViewControllers/DownloadHistory.cpp b/src/UI/ViewControllers/DownloadHistory.cpp index 504a533..5fa34e3 100644 --- a/src/UI/ViewControllers/DownloadHistory.cpp +++ b/src/UI/ViewControllers/DownloadHistory.cpp @@ -327,16 +327,20 @@ void ViewControllers::DownloadHistoryViewController::ProcessDownloads(bool force hasUnloadedDownloads = false; } } - if (fcInstance && fcInstance->SongListController && fcInstance->SongListController->currentSong != nullptr) { - if (currentEntry->status == DownloadHistoryEntry::DownloadStatus::Downloaded) { - // NESTING HELLLL - if (fcInstance->SongListController->currentSong->hash() == currentEntry->hash) { - fcInstance->SongListController->SetIsDownloaded(true); - } - fcInstance->SongListController->songListTable()->RefreshCells(false, true); - } else { - if (fcInstance->SongListController->currentSong->hash() == currentEntry->hash) { - fcInstance->SongListController->SetIsDownloaded(false); + + if (fcInstance && fcInstance->SongListController) { + auto currentSong = fcInstance->SongListController->GetCurrentSong(); + if (currentSong != nullptr) { + if (currentEntry->status == DownloadHistoryEntry::DownloadStatus::Downloaded) { + // NESTING HELLLL + if (currentSong->hash() == currentEntry->hash) { + fcInstance->SongListController->SetIsDownloaded(true); + } + fcInstance->SongListController->songListTable()->RefreshCells(false, true); + } else { + if (currentSong->hash() == currentEntry->hash) { + fcInstance->SongListController->SetIsDownloaded(false); + } } } } diff --git a/src/UI/ViewControllers/SongList.cpp b/src/UI/ViewControllers/SongList.cpp index b94ddab..dd7bd57 100644 --- a/src/UI/ViewControllers/SongList.cpp +++ b/src/UI/ViewControllers/SongList.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "assets.hpp" @@ -375,8 +376,8 @@ void ViewControllers::SongListController::ShowSettings() { // Song buttons void ViewControllers::SongListController::Download() { #ifdef SONGDOWNLOADER - - auto songData = this->currentSong; + auto currentSong = GetCurrentSong(); + auto songData = currentSong; if (songData != nullptr) { fcInstance->DownloadHistoryViewController->TryAddDownload(songData); @@ -481,6 +482,7 @@ void ViewControllers::SongListController::Play() { } void ViewControllers::SongListController::PlaySong(SongDetailsCache::Song const* songToPlay) { + auto currentSong = GetCurrentSong(); if (songToPlay == nullptr) { songToPlay = currentSong; if (currentSong == nullptr) { @@ -543,12 +545,14 @@ void ViewControllers::SongListController::ShowBatchDownload() { } void ViewControllers::SongListController::ShowSongDetails() { - if (this->currentSong) { - uploadDetailsModal->OpenModal(this->currentSong); + auto currentSong = GetCurrentSong(); + if (currentSong) { + uploadDetailsModal->OpenModal(currentSong); } } void ViewControllers::SongListController::UpdateDetails() { + auto currentSong = GetCurrentSong(); if (currentSong == nullptr) { return; } @@ -611,7 +615,12 @@ void ViewControllers::SongListController::UpdateDetails() { if (success) { std::vector data = bytes; DEBUG("Image size: {}", pretty_bytes(bytes.size())); - if (song->hash() != this->currentSong->hash()) { + auto currentSong = GetCurrentSong(); + // Return if the song has changed somehow + if (currentSong == nullptr) { + return; + } + if (song->hash() != currentSong->hash()) { return; } auto spriteArray = ArrayW(data); @@ -675,12 +684,13 @@ void ViewControllers::SongListController::UpdateDetails() { } void ViewControllers::SongListController::FilterByUploader() { - if (!this->currentSong) { + auto currentSong = GetCurrentSong(); + if (!currentSong) { return; } - fcInstance->FilterViewController->uploadersString = this->currentSong->uploaderName(); - SetStringSettingValue(fcInstance->FilterViewController->uploadersStringControl, (std::string) this->currentSong->uploaderName()); + fcInstance->FilterViewController->uploadersString = currentSong->uploaderName(); + SetStringSettingValue(fcInstance->FilterViewController->uploadersStringControl, (std::string) currentSong->uploaderName()); fcInstance->FilterViewController->UpdateFilterSettings(); DEBUG("FilterByUploader"); } @@ -707,10 +717,12 @@ void ViewControllers::SongListController::SortAndFilterSongs(FilterTypes::SortMo void ViewControllers::SongListController::SetSelectedSong(SongDetailsCache::Song const* song) { // TODO: Fill all fields, download image, activate buttons - if (currentSong != nullptr && currentSong->hash() == song->hash()) { + auto prevSong = GetCurrentSong(); + if (prevSong != nullptr && song != nullptr && prevSong->hash() == song->hash()) { return; } - currentSong = song; + + SetCurrentSong(song); DEBUG("Updating details"); this->UpdateDetails(); @@ -762,6 +774,7 @@ void ViewControllers::SongListController::SearchDone() { } } + auto currentSong = GetCurrentSong(); // Reset song list table selection if (!currentSong) { SelectSong(songListTable(), 0); @@ -816,13 +829,34 @@ void ViewControllers::SongListController::PlayerDataLoaded() { } void ViewControllers::SongListController::OnSongsLoaded(std::span songs) { + auto currentSong = GetCurrentSong(); if (currentSong == nullptr) { return; } + // Ensure it runs on the main thread + bool isMainThread = BSML::MainThreadScheduler::CurrentThreadIsMainThread(); + if (!isMainThread) { + ERROR("Calling OnSongsLoaded not on the main thread, sending to main thread"); + BSML::MainThreadScheduler::Schedule([this, songs] { + this->OnSongsLoaded(songs); + }); + return; + } + auto song = currentSong; auto beatmap = SongCore::API::Loading::GetLevelByHash(std::string(song->hash())); bool loaded = beatmap != nullptr; SetIsDownloaded(loaded); } + +SongDetailsCache::Song const* ViewControllers::SongListController::GetCurrentSong() { + std::shared_lock lock(_currentSongMutex); + return _currentSong; +} + +void ViewControllers::SongListController::SetCurrentSong(SongDetailsCache::Song const* song) { + std::unique_lock lock(_currentSongMutex); + _currentSong = song; +}