diff --git a/src/MusicWheel.cpp b/src/MusicWheel.cpp index 5a15cba5f2..94f64178df 100644 --- a/src/MusicWheel.cpp +++ b/src/MusicWheel.cpp @@ -542,7 +542,8 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh split( MODE_MENU_CHOICE_NAMES, ",", vsNames ); for( unsigned i=0; iTrace( "Adding mode menu item %s", vsNames[i].c_str() ); + MusicWheelItemData wid( WheelItemDataType_Sort, nullptr, "", nullptr, nullptr, SORT_MENU_COLOR, 0 ); wid.m_pAction = HiddenPtr( new GameCommand ); wid.m_pAction->m_sName = vsNames[i]; wid.m_pAction->Load( i, ParseCommands(CHOICE.GetValue(vsNames[i])) ); @@ -725,11 +726,11 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex); iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS; // Add the section item - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sectionName, nullptr, colorSection, songs.size()) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sectionName, nullptr, nullptr, colorSection, songs.size()) ); // Add all the songs in this section for (auto const& song : songs) { - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, sectionName, nullptr, SONGMAN->GetSongColor(song), 0) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, sectionName, nullptr, nullptr, SONGMAN->GetSongColor(song), 0) ); } } } @@ -742,15 +743,66 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh RageColor colorSection = SECTION_COLORS.GetValue(iSectionColorIndex); iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS; // Add the section item - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, ssprintf("%d",sectionName), nullptr, colorSection, songs.size()) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, ssprintf("%d",sectionName), nullptr, nullptr, colorSection, songs.size()) ); // Add all the songs in this section for (auto const& song : songs) { - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, ssprintf("%d",sectionName), nullptr, SONGMAN->GetSongColor(song), 0) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, song, ssprintf("%d",sectionName), nullptr, nullptr, SONGMAN->GetSongColor(song), 0) ); } } } break; + case SORT_GROUP: + for( unsigned i=0; i< arraySongs.size(); i++ ) + { + Song* pSong = arraySongs[i]; + LOG->Trace("SORT_GROUP PREPACK"); + Pack* pPack = pSong->GetPack(); + if( bUseSections ) + { + // Print out everything about the pack and song + LOG->Trace("Sort Title: %s", pPack->m_sSortTitle); + LOG->Trace("Group Name: %s", pPack->m_sGroupName); + LOG->Trace("Has PackIni: %s", pPack->m_bHasPackIni ? "true" : "false"); + LOG->Trace("Display Title: %s", pPack->m_sDisplayTitle); + LOG->Trace("Song Title: %s", pSong->GetDisplayFullTitle()); + LOG->Trace("Group Name from Song: %s", pSong->m_sGroupName.c_str()); + LOG->Trace("Offset: %d", pPack->m_iSyncOffset); + RString sThisSection = pSong->GetPack()->m_sSortTitle; + if (pPack->m_bHasPackIni) { + LOG->Trace("HE GOT DA INI"); + sThisSection = pPack->m_sGroupName; + } + if( sThisSection != sLastSection ) + { + int iSectionCount = 0; + // Count songs in this section + unsigned j; + LOG->Trace("SORT_GROUP AYA21YA: %s", sThisSection.c_str()); + for( j=i; j < arraySongs.size(); j++ ) + { + if( SongUtil::GetSectionNameFromSongAndSort( arraySongs[j], so ) != sThisSection ) + break; + } + LOG->Trace("SORT_GROUP AYA22YA: %s", sThisSection.c_str()); + iSectionCount = j-i; + + // new section, make a section item + // todo: preferred sort section color handling? -aj + RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(sThisSection) : SECTION_COLORS.GetValue(iSectionColorIndex); + iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS; + LOG->Trace("SORT_GROUP BEFORE: %s", sThisSection.c_str()); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, pPack, colorSection, iSectionCount) ); + sLastSection = sThisSection; + LOG->Trace("SORT_GROUP AFTER: %s", sLastSection.c_str()); + } + } + LOG->Trace("SORT_GROUP AYAYA: %s", sLastSection.c_str()); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, pSong, sLastSection, nullptr, pPack, SONGMAN->GetSongColor(pSong), 0) ); + LOG->Trace("SORT_GROUP Pushed back Successfully: %s", sLastSection.c_str()); + } + break; + default: for( unsigned i=0; i< arraySongs.size(); i++ ) { @@ -773,13 +825,13 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh // new section, make a section item // todo: preferred sort section color handling? -aj - RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(pSong->m_sGroupName) : SECTION_COLORS.GetValue(iSectionColorIndex); + RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(sThisSection) : SECTION_COLORS.GetValue(iSectionColorIndex); iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS; - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, colorSection, iSectionCount) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, nullptr, colorSection, iSectionCount) ); sLastSection = sThisSection; } } - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, pSong, sLastSection, nullptr, SONGMAN->GetSongColor(pSong), 0) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Song, pSong, sLastSection, nullptr, pSong->GetPack(), SONGMAN->GetSongColor(pSong), 0) ); } break; } @@ -788,7 +840,7 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh { // todo: allow themers to change the order of the items. -aj if( SHOW_ROULETTE ) - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Roulette, nullptr, "", nullptr, ROULETTE_COLOR, 0) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Roulette, nullptr, "", nullptr, nullptr, ROULETTE_COLOR, 0) ); // Only add WheelItemDataType_Random and WheelItemDataType_Portal if there's at least // one song on the list. @@ -798,17 +850,18 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh bFoundAnySong = true; if( SHOW_RANDOM && bFoundAnySong ) - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Random, nullptr, "", nullptr, RANDOM_COLOR, 0) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Random, nullptr, "", nullptr, nullptr, RANDOM_COLOR, 0) ); + LOG->Trace("CRINGLEBINGLE3"); if( SHOW_PORTAL && bFoundAnySong ) - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Portal, nullptr, "", nullptr, PORTAL_COLOR, 0) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Portal, nullptr, "", nullptr, nullptr, PORTAL_COLOR, 0) ); // add custom wheel items std::vector vsNames; split( CUSTOM_WHEEL_ITEM_NAMES, ",", vsNames ); for( unsigned i=0; i( new GameCommand ); wid.m_pAction->m_sName = vsNames[i]; wid.m_pAction->Load( i, ParseCommands(CUSTOM_CHOICES.GetValue(vsNames[i])) ); @@ -934,12 +987,13 @@ void MusicWheel::BuildWheelItemDatas( std::vector &arrayWh { RageColor c = SECTION_COLORS.GetValue(iSectionColorIndex); iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS; - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, c, 0) ); + LOG->Trace("CRINGLEBINGLE7"); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, sThisSection, nullptr, nullptr, c, 0) ); sLastSection = sThisSection; } RageColor c = ( pCourse->m_sGroupName.size() == 0 ) ? pCourse->GetColor() : SONGMAN->GetCourseColor(pCourse); - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Course, nullptr, sThisSection, pCourse, c, 0) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Course, nullptr, sThisSection, pCourse, nullptr, c, 0) ); } break; } @@ -1153,7 +1207,7 @@ void MusicWheel::FilterWheelItemDatas(std::vector &aUnFilt // If we've filtered all items, insert a dummy. if( aFilteredData.empty() ) - aFilteredData.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, EMPTY_STRING, nullptr, EMPTY_COLOR, 0) ); + aFilteredData.push_back( new MusicWheelItemData(WheelItemDataType_Section, nullptr, EMPTY_STRING, nullptr, nullptr, EMPTY_COLOR, 0) ); } void MusicWheel::UpdateSwitch() diff --git a/src/MusicWheelItem.cpp b/src/MusicWheelItem.cpp index 2ad1955712..1ec7535ae4 100644 --- a/src/MusicWheelItem.cpp +++ b/src/MusicWheelItem.cpp @@ -34,10 +34,10 @@ static const char *MusicWheelItemTypeNames[] = { XToString( MusicWheelItemType ); MusicWheelItemData::MusicWheelItemData( WheelItemDataType type, Song* pSong, - RString sSectionName, Course* pCourse, + RString sSectionName, Course* pCourse, Pack* pPack, RageColor color, int iSectionCount ): WheelItemBaseData(type, sSectionName, color), - m_pCourse(pCourse), m_pSong(pSong), m_Flags(WheelNotifyIcon::Flags()), + m_pCourse(pCourse), m_pSong(pSong), m_pPack(pPack), m_Flags(WheelNotifyIcon::Flags()), m_iSectionCount(iSectionCount), m_sLabel(""), m_pAction() {} MusicWheelItem::MusicWheelItem( RString sType ): @@ -209,6 +209,7 @@ void MusicWheelItem::LoadFromWheelItemData( const WheelItemBaseData *pData, int { DEFAULT_FAIL( pWID->m_Type ); case WheelItemDataType_Song: + LOG->Trace( "MusicWheelItem::LoadFromWheelItemData() - Song" ); type = MusicWheelItemType_Song; m_TextBanner.SetFromSong( pWID->m_pSong ); @@ -222,15 +223,33 @@ void MusicWheelItem::LoadFromWheelItemData( const WheelItemBaseData *pData, int break; case WheelItemDataType_Section: { - sDisplayName = SONGMAN->ShortenGroupName(pWID->m_sText); - + LOG->Trace( "MusicWheelItem::LoadFromWheelItemData() - Section" ); + if ( pWID->m_pPack == nullptr ) { + LOG->Trace( "MusicWheelItem::LoadFromWheelItemData() - Section with no pack" ); + sDisplayName = SONGMAN->ShortenGroupName(pWID->m_sText); + } + else { + if ( pWID->m_pPack->m_sDisplayTitle == "" ) { + LOG->Trace( "MusicWheelItem::LoadFromWheelItemData() - Section with no display title" ); + } + // Log everything about the wheel + LOG->Trace( "Pack Display Title: %s", pWID->m_pPack->m_sDisplayTitle.c_str() ); + LOG->Trace( "Pack Sort Title: %s", pWID->m_pPack->m_sSortTitle.c_str() ); + LOG->Trace( "Pack Group Name: %s", pWID->m_pPack->m_sGroupName.c_str() ); + LOG->Trace( "Pack Has PackIni: %s", pWID->m_pPack->m_bHasPackIni ? "true" : "false" ); + sDisplayName = SONGMAN->ShortenGroupName(pWID->m_pPack->m_sDisplayTitle); + LOG->Trace( "Pack Display Title Shortened: %s", sDisplayName.c_str() ); + } if( GAMESTATE->sExpandedSectionName == pWID->m_sText ) type = MusicWheelItemType_SectionExpanded; else type = MusicWheelItemType_SectionCollapsed; + LOG->Trace( "MusicWheelItem::LoadFromWheelItemData() - SectionDone1: %s", sDisplayName.c_str() ); + m_pTextSectionCount->SetText( ssprintf("%d",pWID->m_iSectionCount) ); m_pTextSectionCount->SetVisible( true ); + LOG->Trace( "MusicWheelItem::LoadFromWheelItemData() - SectionDone: %s", sDisplayName.c_str() ); } break; case WheelItemDataType_Course: @@ -241,6 +260,7 @@ void MusicWheelItem::LoadFromWheelItemData( const WheelItemBaseData *pData, int m_WheelNotifyIcon.SetVisible( true ); break; case WheelItemDataType_Sort: + LOG->Trace( "MusicWheelItem::LoadFromWheelItemData() - Sort" ); sDisplayName = pWID->m_sLabel; // hack to get mode items working. -freem if( pWID->m_pAction->m_pm != PlayMode_Invalid ) diff --git a/src/MusicWheelItem.h b/src/MusicWheelItem.h index bfc94a3abf..b2f33cc6a9 100644 --- a/src/MusicWheelItem.h +++ b/src/MusicWheelItem.h @@ -6,6 +6,7 @@ #include "WheelNotifyIcon.h" #include "TextBanner.h" #include "GameConstantsAndTypes.h" +#include "Song.h" #include "GameCommand.h" #include "WheelItemBase.h" #include "AutoActor.h" @@ -13,6 +14,7 @@ class Course; class Song; +struct Pack; struct MusicWheelItemData; @@ -62,14 +64,15 @@ private: struct MusicWheelItemData : public WheelItemBaseData { - MusicWheelItemData() : m_pCourse(nullptr), m_pSong(nullptr), m_Flags(), + MusicWheelItemData() : m_pCourse(nullptr), m_pSong(nullptr), m_pPack(nullptr), m_Flags(), m_iSectionCount(0), m_sLabel(""), m_pAction() { } MusicWheelItemData( WheelItemDataType type, Song* pSong, - RString sSectionName, Course* pCourse, + RString sSectionName, Course* pCourse, Pack* pPack, RageColor color, int iSectionCount ); Course* m_pCourse; Song* m_pSong; + Pack* m_pPack; WheelNotifyIcon::Flags m_Flags; // for TYPE_SECTION diff --git a/src/Profile.cpp b/src/Profile.cpp index e7ebc8472d..41bde77ad9 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -1195,6 +1195,46 @@ void Profile::LoadSongsFromDir(RString const& dir, ProfileSlot prof_slot) RageTimer song_load_start_time; song_load_start_time.Touch(); FILEMAN->GetDirListing(songs_folder + "/*", song_folders, true, true); + // Check for pack.ini + + RString sGroupIniPath = songs_folder + "/pack.ini"; + RString sDisplayTitle; + RString SortTitle; + RString TranslitTitle; + RString Series; + int iOffset = 0; + + Pack pack; + if( FILEMAN->DoesFileExist( sGroupIniPath ) ) + { + IniFile ini; + ini.ReadFile( sGroupIniPath ); + ini.GetValue( "Group", "DisplayTitle", sDisplayTitle ); + if (sDisplayTitle.empty()) + sDisplayTitle = "Custom Songs"; + ini.GetValue( "Group", "SortTitle", SortTitle ); + if (SortTitle.empty()) + SortTitle = sDisplayTitle; + ini.GetValue( "Group", "TranslitTitle", TranslitTitle ); + if (TranslitTitle.empty()) + TranslitTitle = sDisplayTitle; + ini.GetValue( "Group", "Series", Series ); + ini.GetValue( "Group", "Offset", iOffset ); + } else { + sDisplayTitle = "Custom Songs"; + SortTitle = "Custom Songs"; + TranslitTitle =""; + Series = ""; + iOffset = 0; + } + pack.m_sDisplayTitle = sDisplayTitle; + pack.m_sSortTitle = SortTitle; + pack.m_sTranslitTitle = TranslitTitle; + pack.m_sSeries = Series; + pack.m_iSyncOffset = iOffset; + pack.m_sPath = songs_folder; + pack.m_sGroupName = "Custom Songs"; + StripCvsAndSvn(song_folders); StripMacResourceForks(song_folders); LOG->Trace("Found %i songs in profile.", int(song_folders.size())); diff --git a/src/Song.cpp b/src/Song.cpp index 4cdce33d39..6bf953ee6b 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -276,6 +276,11 @@ const RString &Song::GetSongFilePath() const * into Song.h, which is heavily used. */ static std::set BlacklistedImages; +Pack* Song::GetPack() const +{ + return SONGMAN->GetPackFromGroupName(m_sGroupName); +} + /* If PREFSMAN->m_bFastLoad is true, always load from cache if possible. * Don't read the contents of sDir if we can avoid it. That means we can't call * HasMusic(), HasBanner() or GetHashForDirectory(). @@ -457,11 +462,14 @@ bool Song::LoadFromSongDir(RString sDir, bool load_autosave, ProfileSlot from_pr return true; // do load this song } + + /* This function feels EXTREMELY hacky - copying things on top of pointers so * they don't break elsewhere. Maybe it could be rewritten to politely ask the * Song/Steps objects to reload themselves. -- djpohly */ bool Song::ReloadFromSongDir( RString sDir ) { + LOG->Trace("Reload From Song Dir Pack Test: %s", GetPack()->m_sGroupName.c_str()); // Remove the cache file to force the song to reload from its dir instead // of loading from the cache. -Kyz FILEMAN->Remove(GetCacheFilePath()); @@ -469,6 +477,7 @@ bool Song::ReloadFromSongDir( RString sDir ) RemoveAutoGenNotes(); std::vector vOldSteps = m_vpSteps; + Song copy; if( !copy.LoadFromSongDir( sDir ) ) return false; diff --git a/src/Song.h b/src/Song.h index 0196dae14c..ff1c6c88b9 100644 --- a/src/Song.h +++ b/src/Song.h @@ -64,6 +64,20 @@ struct LyricSegment RageColor m_Color; /** @brief The color of the lyrics. */ }; + +struct Pack +{ + RString m_sDisplayTitle; + RString m_sSortTitle; + RString m_sPath; + RString m_sGroupName; + RString m_sTranslitTitle; + RString m_sSeries; + int m_iSyncOffset; + bool m_bHasPackIni; + int iTotalSongs; +}; + /** @brief Holds all music metadata and steps for one song. */ class Song { @@ -196,6 +210,7 @@ public: /** @brief The transliterated artist of the Song, if it exists. */ RString m_sArtistTranslit; + RString m_sFileHash; RString GetFileHash(); @@ -206,6 +221,8 @@ public: RString GetDisplayArtist() const; RString GetMainTitle() const; + Pack* GetPack() const; + /** * @brief Retrieve the transliterated title, or the main title if there is no translit. * @return the proper title. */ @@ -276,7 +293,7 @@ public: RString GetBannerPath() const; RString GetJacketPath() const; RString GetCDImagePath() const; - RString GetDiscPath() const; + RString GetDiscPath() const; RString GetLyricsPath() const; RString GetBackgroundPath() const; RString GetCDTitlePath() const; diff --git a/src/SongManager.cpp b/src/SongManager.cpp index af07e60c23..c059bf043f 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -267,7 +267,7 @@ void SongManager::SanityCheckGroupDir( RString sDir ) const } } -void SongManager::AddGroup( RString sDir, RString sGroupDirName ) +void SongManager::AddGroup( RString sDir, RString sGroupDirName, Pack pack ) { unsigned j; for(j = 0; j < m_sSongGroupNames.size(); ++j) @@ -335,6 +335,28 @@ void SongManager::AddGroup( RString sDir, RString sGroupDirName ) */ m_sSongGroupNames.push_back( sGroupDirName ); m_sSongGroupBannerPaths.push_back( sBannerPath ); + if (m_mapGroupToPack.find(sGroupDirName) == m_mapGroupToPack.end()) + { + m_mapGroupToPack[sGroupDirName] = pack; + } else { + LOG->Trace("SongManager::AddGroup: Group %s already has a pack. Ignoring pack %s.", sGroupDirName.c_str(), pack.m_sDisplayTitle.c_str()); + } + + + + // Add the pack to its series if the pack has one and if the series exists + // if( pack.m_sSeries != "" ) + // { + // if (m_mapSeries.find(pack.m_sSeries) == m_mapSeries.end()) + // { + // m_mapSeries[pack.m_sSeries] = std::vector(); + // m_mapSeries[pack.m_sSeries].push_back(pack); + + // } else { + // m_mapSeries[pack.m_sSeries]->packs.push_back(pack); + // } + // } + //m_sSongGroupBackgroundPaths.push_back( sBackgroundPath ); } @@ -405,6 +427,7 @@ void SongManager::LoadSongDir( RString sDir, LoadingWindow *ld, bool onlyAdditio groupIndex = 0; songIndex = 0; + for (RString const &sGroupDirName : arrayGroupDirs) // foreach dir in /Songs/ { std::vector &arraySongDirs = arrayGroupSongDirs[groupIndex++]; @@ -415,6 +438,52 @@ void SongManager::LoadSongDir( RString sDir, LoadingWindow *ld, bool onlyAdditio SongPointerVector& index_entry = m_mapSongGroupIndex[sGroupDirName]; RString group_base_name= Basename(sGroupDirName); + + RString sGroupIniPath = sDir + sGroupDirName + "/pack.ini"; + RString sDisplayTitle = sGroupDirName; + RString SortTitle = sGroupDirName; + RString TranslitTitle = sGroupDirName; + RString Series = ""; + int iOffset = 0; + + Pack pack; + if( FILEMAN->DoesFileExist( sGroupIniPath ) && arraySongDirs.size() > 0 ) + { + LOG->Trace("Loading pack.ini for \"%s\"", (sDir+sGroupDirName).c_str() ); + IniFile ini; + ini.ReadFile( sGroupIniPath ); + ini.GetValue( "Group", "DisplayTitle", sDisplayTitle ); + if (sDisplayTitle.empty()) + sDisplayTitle = group_base_name; + ini.GetValue( "Group", "SortTitle", SortTitle ); + if (SortTitle.empty()) + SortTitle = sDisplayTitle; + ini.GetValue( "Group", "TranslitTitle", TranslitTitle ); + if (TranslitTitle.empty()) + TranslitTitle = sDisplayTitle; + ini.GetValue( "Group", "Series", Series ); + ini.GetValue( "Group", "SyncOffsetMs", iOffset ); + LOG->Trace("Loaded pack.ini for \"%s\"", (sDir+sGroupDirName).c_str() ); + // LOG THE RECEIVED INFO + LOG->Trace("DisplayTitle: %s", sDisplayTitle.c_str()); + LOG->Trace("SortTitle: %s", SortTitle.c_str()); + pack.m_bHasPackIni = true; + } else { + LOG->Trace("No pack.ini found for \"%s\"", (sDir+sGroupDirName).c_str() ); + LOG-> Trace("Using default values for pack.ini"); + LOG-> Trace("DisplayTitle: %s", sDisplayTitle.c_str()); + LOG-> Trace("SortTitle: %s", SortTitle.c_str()); + pack.m_bHasPackIni = false; + } + pack.m_sDisplayTitle = sDisplayTitle; + pack.m_sSortTitle = SortTitle; + pack.m_sTranslitTitle = TranslitTitle; + pack.m_sSeries = Series; + pack.m_iSyncOffset = iOffset; + pack.m_sPath = sDir + sGroupDirName; + pack.m_sGroupName = group_base_name; + + for( unsigned j=0; j< arraySongDirs.size(); ++j ) // for each song dir { RString sSongDirName = arraySongDirs[j]; @@ -442,7 +511,7 @@ void SongManager::LoadSongDir( RString sDir, LoadingWindow *ld, bool onlyAdditio } Song* pNewSong = new Song; - if( !pNewSong->LoadFromSongDir( sSongDirName ) ) + if( !pNewSong->LoadFromSongDir( sSongDirName) ) { // The song failed to load. delete pNewSong; @@ -459,9 +528,12 @@ void SongManager::LoadSongDir( RString sDir, LoadingWindow *ld, bool onlyAdditio // Don't add the group name if we didn't load any songs in this group. if(!loaded) continue; + // Save amount of songs + pack.iTotalSongs = loaded; // Add this group to the group array. - AddGroup(sDir, sGroupDirName); + AddGroup(sDir, sGroupDirName, pack); + // Cache and load the group banner. (and background if it has one -aj) IMAGECACHE->CacheImage( "Banner", GetSongGroupBannerPath(sGroupDirName) ); @@ -861,6 +933,14 @@ std::vector SongManager::GetPreferredSortSongsBySectionName( const RStrin return AddTo; } +Pack* SongManager::GetPackFromGroupName( const RString &sGroupName ) const +{ + std::map::const_iterator iter = m_mapGroupToPack.find( sGroupName ); + if( iter != m_mapGroupToPack.end() ) + return const_cast(&iter->second); + return nullptr; +} + std::vector SongManager::GetPreferredSortSectionNames() const { std::vector sectionNames; diff --git a/src/SongManager.h b/src/SongManager.h index b55ab4ba69..97e048ea01 100644 --- a/src/SongManager.h +++ b/src/SongManager.h @@ -18,7 +18,7 @@ struct lua_State; #include "ThemeMetric.h" #include "RageTexturePreloader.h" #include "RageUtil.h" - +#include "Song.h" #include #include @@ -62,7 +62,7 @@ public: int GetNumStepsLoadedFromProfile(); void FreeAllLoadedFromProfile( ProfileSlot slot = ProfileSlot_Invalid ); - void LoadGroupSymLinks( RString sDir, RString sGroupFolder ); + void LoadGroupSymLinks( RString sDir, RString sGroupFolder); /** * @brief Initialize all courses from disk @@ -146,6 +146,9 @@ public: void GetPreferredSortSongs( std::vector &AddTo ) const; std::map> GetPreferredSortSongsMap() const { return m_mapPreferredSectionToSongs;}; RString SongToPreferredSortSectionName( const Song *pSong ) const; + std::map GetGroupPackMap() const { return m_mapGroupToPack;}; + std::map> GetSeriesPackMap() const { return m_mapSeries;}; + Pack* GetPackFromGroupName( const RString &sGroupName ) const; std::vector GetPreferredSortSectionNames() const; std::vector GetPreferredSortSongsBySectionName( const RString &sSectionName ) const; void GetPreferredSortSongsBySectionName( const RString &sSectionName, std::vector &AddTo ) const; @@ -212,7 +215,7 @@ protected: 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 ); + void AddGroup( RString sDir, RString sGroupDirName, Pack pack ); int GetNumEditsLoadedFromProfile( ProfileSlot slot ) const; void AddSongToList(Song* new_song); @@ -221,6 +224,7 @@ protected: std::map m_SongsByDir; std::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. */ std::vector m_pDeletedSongs; @@ -242,6 +246,8 @@ protected: std::vector m_sSongGroupNames; std::vector m_sSongGroupBannerPaths; // each song group may have a banner associated with it //vector m_sSongGroupBackgroundPaths; // each song group may have a background associated with it (very rarely) + std::map m_mapGroupToPack; + std::map> m_mapSeries; struct Comp { bool operator()(const RString& s, const RString &t) const { return CompareRStringsAsc(s,t); } }; typedef std::vector SongPointerVector; diff --git a/src/SongUtil.cpp b/src/SongUtil.cpp index be579a0eb0..7df8d850e5 100644 --- a/src/SongUtil.cpp +++ b/src/SongUtil.cpp @@ -595,13 +595,31 @@ void SongUtil::SortSongPointerArrayByGenre( std::vector &vpSongsInOut ) int SongUtil::CompareSongPointersByGroup(const Song *pSong1, const Song *pSong2) { - return pSong1->m_sGroupName < pSong2->m_sGroupName; + // Check if the sort title exists + if( pSong1->GetPack()->m_sSortTitle.empty() || pSong2->GetPack()->m_sSortTitle.empty() ) { + // LOG the DEETS + LOG->Warn("SongUtil::CompareSongPointersByGroup: Song %s or %s has an empty group name. Using group name instead.", pSong1->m_sSongName.c_str(), pSong2->m_sSongName.c_str()); + return pSong1->m_sGroupName < pSong2->m_sGroupName; + } else { + return pSong1->GetPack()->m_sSortTitle < pSong2->GetPack()->m_sSortTitle; + } } static int CompareSongPointersByGroupAndTitle( const Song *pSong1, const Song *pSong2 ) { - const RString &sGroup1 = pSong1->m_sGroupName; - const RString &sGroup2 = pSong2->m_sGroupName; + + LOG->Trace("SongUtil::CompareSongPointersByGroupAndTitle: %s %s", pSong1->m_sSongName.c_str(), pSong2->m_sSongName.c_str()); + // Check if the sort title exists + const RString &sGroup1 = pSong1->GetPack()->m_sSortTitle; + const RString &sGroup2 = pSong2->GetPack()->m_sSortTitle; + LOG->Trace(pSong1->GetDisplayMainTitle().c_str()); + LOG->Trace(sGroup1.c_str()); + LOG->Trace(sGroup2.c_str()); + LOG->Trace(pSong2->GetPack()->m_sGroupName.c_str()); + LOG->Trace(pSong2->GetPack()->m_sDisplayTitle.c_str()); + // Log whether bHasPackIni is true or false + LOG->Trace("bHasPackIni: %s", pSong1->GetPack()->m_bHasPackIni ? "true" : "false"); + LOG->Trace("EUREKA!!! %s %s", sGroup1.c_str(), sGroup2.c_str()); if( sGroup1 < sGroup2 ) return true; @@ -610,6 +628,7 @@ static int CompareSongPointersByGroupAndTitle( const Song *pSong1, const Song *p /* Same group; compare by name. */ return CompareSongPointersByTitle( pSong1, pSong2 ); + } void SongUtil::SortSongPointerArrayByGroupAndTitle( std::vector &vpSongsInOut ) @@ -645,7 +664,7 @@ RString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so return SONGMAN->SongToPreferredSortSectionName( pSong ); case SORT_GROUP: // guaranteed not empty - return pSong->m_sGroupName; + return pSong->GetPack()->m_sSortTitle; case SORT_TITLE: case SORT_ARTIST: {