1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
|
//========= 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 "vgui_controls/Frame.h"
#include "filesystem.h"
#include "utlsymbol.h"
// Forward declarations
namespace vgui
{
class MenuButton;
class Button;
class Slider;
class IScheme;
class FileOpenDialog;
class DirectorySelectDialog;
};
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
|