//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// #ifndef MP3PLAYER_H #define MP3PLAYER_H #ifdef _WIN32 #pragma once #endif // // The MP3 player has a menu button for setting options, opening files, etc. // it has a tree control to show the high level categories // It has a property sheet to switch between the file view and the current // playlist // it has a list view to show the actual files in either view #include "filesystem.h" #include "utlsymbol.h" #include "vgui_controls/Frame.h" // Forward declarations namespace vgui { class MenuButton; class Button; class Slider; class IScheme; class FileOpenDialog; class DirectorySelectDialog; }; // namespace vgui class CMP3FileSheet; class CMP3TreeControl; class CMP3SongProgress; //----------------------------------------------------------------------------- // Purpose: This is the core MP3 file element //----------------------------------------------------------------------------- struct MP3File_t { enum { FLAG_UNKNOWN = 0, // File came from steam cache/game data, rather than the user's "My // Music" folder... FLAG_FROMGAME, // File came from directory outside of game data directory FLAG_FROMFS }; MP3File_t() { filename = 0; playbackfilename = 0; flags = FLAG_UNKNOWN; dirnum = -1; shortname = UTL_INVAL_SYMBOL; } int flags; FileNameHandle_t filename; FileNameHandle_t playbackfilename; // in case we had to make a local copy // somewhere else... CUtlSymbol shortname; int dirnum; }; //----------------------------------------------------------------------------- // Purpose: A directory has a name, 0 or more subdirectories and 0 or more mp3 // files in it //----------------------------------------------------------------------------- struct MP3Dir_t { MP3Dir_t() : m_DirName(UTL_INVAL_SYMBOL), m_FullDirPath(UTL_INVAL_SYMBOL) {} ~MP3Dir_t() { DeleteSubdirectories(); } void DeleteSubdirectories() { int i, c; c = m_Subdirectories.Count(); for (i = c - 1; i >= 0; --i) { delete m_Subdirectories[i]; } m_Subdirectories.RemoveAll(); } MP3Dir_t(const MP3Dir_t &src) { m_DirName = src.m_DirName; m_FullDirPath = src.m_FullDirPath; int i, c; c = src.m_Subdirectories.Count(); for (i = 0; i < c; ++i) { MP3Dir_t *subCopy = new MP3Dir_t(*src.m_Subdirectories[i]); m_Subdirectories.AddToTail(subCopy); } c = src.m_FilesInDirectory.Count(); for (i = 0; i < c; ++i) { m_FilesInDirectory.AddToTail(src.m_FilesInDirectory[i]); } } MP3Dir_t &operator=(const MP3Dir_t &src) { if (this == &src) { return *this; } m_DirName = src.m_DirName; m_FullDirPath = src.m_FullDirPath; DeleteSubdirectories(); m_FilesInDirectory.RemoveAll(); int i, c; c = src.m_Subdirectories.Count(); for (i = 0; i < c; ++i) { // make a copy MP3Dir_t *subCopy = new MP3Dir_t(*src.m_Subdirectories[i]); m_Subdirectories.AddToTail(subCopy); } c = src.m_FilesInDirectory.Count(); for (i = 0; i < c; ++i) { m_FilesInDirectory.AddToTail(src.m_FilesInDirectory[i]); } return *this; } void AddSubDirectory(MP3Dir_t *sub) { m_Subdirectories.AddToTail(sub); } CUtlSymbol m_DirName; // "artist" CUtlSymbol m_FullDirPath; // "artist/album CUtlVector m_Subdirectories; CUtlVector m_FilesInDirectory; }; //----------------------------------------------------------------------------- // Purpose: A sound directory is a root directory which is recursed looking for // .mp3 // We assume that the folders under the sound directory are configured as // artist/album/filename.mp3... //----------------------------------------------------------------------------- struct SoundDirectory_t { explicit SoundDirectory_t(int index) : m_nIndex(index), m_Root(UTL_INVAL_SYMBOL), m_pTree(0), m_bGameSound(false) {} ~SoundDirectory_t() { delete m_pTree; } void SetTree(MP3Dir_t *tree) { if (m_pTree) { delete m_pTree; } m_pTree = tree; } int GetIndex() const { return m_nIndex; } int m_nIndex; CUtlSymbol m_Root; MP3Dir_t *m_pTree; bool m_bGameSound; }; //----------------------------------------------------------------------------- // Purpose: A VGui based .mp3 player //----------------------------------------------------------------------------- class CMP3Player : public vgui::Frame { DECLARE_CLASS_SIMPLE(CMP3Player, vgui::Frame); public: // Construction CMP3Player(vgui::VPANEL parent, char const *panelName); ~CMP3Player(); virtual void SetVisible(bool); // Lookup data MP3File_t *GetSongInfo(int songIndex); // Static singleton accessor static CMP3Player *GetMP3Player(); void AddToPlayList(int songIndex, bool playNow); void RemoveFromPlayList(int songIndex); void ClearPlayList(); void OnLoadPlayList(); void OnSavePlayList(); void OnSavePlayListAs(); void SetPlayListSong(int listIndex); typedef enum { SONG_FROM_UNKNOWN = 0, SONG_FROM_TREE, SONG_FROM_FILELIST, SONG_FROM_PLAYLIST } SongListSource_t; void SelectedSongs(SongListSource_t from, CUtlVector &songIndexList); void EnableAutoAdvance(bool state); protected: virtual void OnCommand(char const *cmd); virtual void ApplySchemeSettings(vgui::IScheme *pScheme); virtual void OnTick(); MESSAGE_FUNC(OnTreeViewItemSelected, "TreeViewItemSelected"); MESSAGE_FUNC(OnSliderMoved, "SliderMoved"); void PopulateTree(); void PopulateLists(); void RecursiveAddToTree(MP3Dir_t *current, int parentIndex); void DeleteSoundDirectories(); // Leave root objects, clear all subdirs void WipeSoundDirectories(); // Remove the _mp3/a45ef65a.mp3 style temp sounds void RemoveTempSounds(); void SplitFile(CUtlVector &splitList, char const *relative); int AddSplitFileToDirectoryTree_R(int songIndex, MP3Dir_t *parent, CUtlVector &splitList, int level); MP3Dir_t *FindOrAddSubdirectory(MP3Dir_t *parent, char const *dirname); int AddFileToDirectoryTree(SoundDirectory_t *dir, char const *relative); void RecursiveFindMP3Files(SoundDirectory_t *root, char const *current, char const *pathID); int AddSong(char const *relative, int dirnum); void RemoveFSSongs(); // Remove all non-built-in .mp3s int FindSong(char const *relative); void PlaySong(int songIndex, float skipTime = 0.0f); void GetLocalCopyOfSong(const MP3File_t &mp3, char *outsong, size_t outlen); float GetMP3Duration(char const *songname); void OnNextTrack(); void OnPrevTrack(); void OnPlay(); void OnStop(); void OnChangeVolume(float newVol); void AddGameSounds(bool recurse); SoundDirectory_t *AddSoundDirectory(char const *fullpath, bool recurse); int FindSoundDirectory(char const *fullpath); bool RestoreDb(char const *filename); void SaveDb(char const *filename); void SaveDbFile(int level, CUtlBuffer &buf, MP3File_t *file, int filenumber); void FlattenDirectoryFileList_R(MP3Dir_t *dir, CUtlVector &list); void SaveDbDirectory(int level, CUtlBuffer &buf, SoundDirectory_t *sd); void RestoreSongs(KeyValues *songs); void RestoreDirectories(KeyValues *dirs); void RestoreDirectory(KeyValues *dir, SoundDirectory_t *sd); void LoadPlayList(char const *filename); void SavePlayList(char const *filename); void SetMostRecentPlayList(char const *filename); void SaveSettings(); void LoadSettings(); // Refresh all directories, built-in sounds void OnRefresh(); void OnSave(); MESSAGE_FUNC_CHARPTR(OnFileSelected, "FileSelected", fullpath); void ShowFileOpenDialog(bool saving); MESSAGE_FUNC_PARAMS(OnDirectorySelected, "DirectorySelected", params); void ShowDirectorySelectDialog(); void GoToNextSong(int skip); // Data private: // UI elements vgui::MenuButton *m_pOptions; CMP3TreeControl *m_pTree; CMP3FileSheet *m_pFileSheet; vgui::Label *m_pCurrentSong; vgui::Label *m_pDuration; CMP3SongProgress *m_pSongProgress; vgui::Button *m_pPlay; vgui::Button *m_pStop; vgui::Button *m_pNext, *m_pPrev; // moving between tracks vgui::CheckButton *m_pMute; vgui::CheckButton *m_pShuffle; vgui::Slider *m_pVolume; // Raw list of all known files CUtlVector m_Files; int m_nFilesAdded; // Indices into m_Files for currently playing songs CUtlVector m_PlayList; // Where in the list we are... int m_nCurrentPlaylistSong; CUtlSymbol m_PlayListFileName; int m_nCurrentFile; // Flag for one-time init bool m_bFirstTime; int m_nCurrentSong; FileNameHandle_t m_LastSong; float m_flCurrentVolume; bool m_bMuted; // Currently playing a song? bool m_bPlaying; int m_nSongGuid; // Song start time float m_SongStart; // Estimated song diration float m_flSongDuration; // For the UI int m_nSongMinutes; int m_nSongSeconds; // List of all added directories CUtlVector m_SoundDirectories; // Selection set CUtlVector m_SelectedSongs; SongListSource_t m_SelectionFrom; // Is database dirty? bool m_bDirty; // Are settings dirty? bool m_bSettingsDirty; // File dialog vgui::DHANDLE m_hSaveLoadPlaylist; // Type of dialog bool m_bSavingFile; // Directory selection dialog vgui::DHANDLE m_hDirectorySelect; bool m_bEnableAutoAdvance; }; #endif // !MP3PLAYER_H