This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

359 lines
10 KiB
C++

//========= 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<MP3Dir_t *> m_Subdirectories;
CUtlVector<int> 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<int> &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<CUtlSymbol> &splitList, char const *relative);
int AddSplitFileToDirectoryTree_R(int songIndex, MP3Dir_t *parent,
CUtlVector<CUtlSymbol> &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<int> &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<MP3File_t> m_Files;
int m_nFilesAdded;
// Indices into m_Files for currently playing songs
CUtlVector<int> 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<SoundDirectory_t *> m_SoundDirectories;
// Selection set
CUtlVector<int> m_SelectedSongs;
SongListSource_t m_SelectionFrom;
// Is database dirty?
bool m_bDirty;
// Are settings dirty?
bool m_bSettingsDirty;
// File dialog
vgui::DHANDLE<vgui::FileOpenDialog> m_hSaveLoadPlaylist;
// Type of dialog
bool m_bSavingFile;
// Directory selection dialog
vgui::DHANDLE<vgui::DirectorySelectDialog> m_hDirectorySelect;
bool m_bEnableAutoAdvance;
};
#endif // !MP3PLAYER_H