Changed: Make media player to play songs from music directory (issue #59)

--HG--
branch : develop
This commit is contained in:
Nimetu 2016-08-25 22:08:05 +03:00
parent 7e1f006647
commit 439916fae8

View file

@ -34,6 +34,8 @@ using namespace NL3D;
extern UDriver *Driver; extern UDriver *Driver;
static const std::string MediaPlayerDirectory("music/");
CMusicPlayer MusicPlayer; CMusicPlayer MusicPlayer;
// *************************************************************************** // ***************************************************************************
@ -170,7 +172,47 @@ void CMusicPlayer::update ()
} }
// *************************************************************************** // ***************************************************************************
static void addFromPlaylist(const std::string &playlist, std::vector<std::string> &filenames)
{
static uint8 utf8Header[] = { 0xefu, 0xbbu, 0xbfu };
// Add playlist
uint i;
// Get the path of the playlist
string basePlaylist = CFile::getPath (playlist);
FILE *file = nlfopen (playlist, "r");
bool useUtf8 = CFile::getExtension(playlist) == "m3u8";
if (file)
{
char line[512];
while (fgets (line, 512, file))
{
string lineStr = trim(std::string(line));
// id a UTF-8 BOM header is present, parse as UTF-8
if (!useUtf8 && lineStr.length() >= 3 && memcmp(line, utf8Header, 3) == 0)
useUtf8 = true;
if (!useUtf8)
{
lineStr = ucstring(line).toUtf8();
lineStr = trim(lineStr);
}
// Not a comment line
if (lineStr[0] != '#')
{
std::string filepath = CFile::getPath(lineStr);
std::string filename = CFile::getFilename(lineStr);
filenames.push_back (CPath::makePathAbsolute(filepath, basePlaylist)+filename);
}
}
fclose (file);
}
}
// ***************************************************************************
class CMusicPlayerPlaySongs: public IActionHandler class CMusicPlayerPlaySongs: public IActionHandler
{ {
public: public:
@ -187,192 +229,82 @@ public:
// no format supported // no format supported
if (extensions.empty()) return; if (extensions.empty()) return;
#ifdef NL_OS_WINDOWS
// Backup the current directory
string currentPath = CPath::getCurrentPath ();
// Hardware mouse
bool wasHardware = IsMouseCursorHardware ();
InitMouseWithCursor (true);
Driver->showCursor (true);
bool oggSupported = false; bool oggSupported = false;
bool mp3Supported = false; bool mp3Supported = false;
std::string message;
for(uint i = 0; i < extensions.size(); ++i) for(uint i = 0; i < extensions.size(); ++i)
{ {
if (extensions[i] == "ogg") if (extensions[i] == "ogg")
{ {
oggSupported = true; oggSupported = true;
message += " ogg";
} }
else if (extensions[i] == "mp3") else if (extensions[i] == "mp3")
{ {
mp3Supported = true; mp3Supported = true;
message += " mp3";
} }
} }
message += " m3u m3u8";
nlinfo("Media player supports: '%s'", message.substr(1).c_str());
std::vector<std::string> filters; // Recursive scan for files from media directory
vector<string> filesToProcess;
string newPath = CPath::standardizePath(MediaPlayerDirectory);
CPath::getPathContent (newPath, true, false, true, filesToProcess);
// supported formats uint i;
filters.push_back("All Supported Files"); // TODO: translate std::vector<std::string> filenames;
std::vector<std::string> playlists;
std::string filter; for (i = 0; i < filesToProcess.size(); ++i)
if (mp3Supported) filter += "*.mp3;*.mp2;*.mp1;";
if (oggSupported) filter += "*.ogg;";
filter += "*.m3u;*.m3u8";
filters.push_back(filter);
// mp3 format
if (mp3Supported)
{ {
filters.push_back("MPEG Audio Files (*.mp3;*.mp2;*.mp1)"); std::string ext = toLower(CFile::getExtension(filesToProcess[i]));
filters.push_back("*.mp3;*.mp2;*.mp1"); if (ext == "ogg")
{
if (oggSupported)
filenames.push_back(filesToProcess[i]);
}
else if (ext == "mp3" || ext == "mp2" || ext == "mp1")
{
if (mp3Supported)
filenames.push_back(filesToProcess[i]);
}
else if (ext == "m3u" || ext == "m3u8")
{
playlists.push_back(filesToProcess[i]);
}
} }
// ogg format // Sort songs by filename
if (oggSupported) sort (filenames.begin(), filenames.end());
// Add songs from playlists
for (i = 0; i < playlists.size(); ++i)
{ {
filters.push_back("Vorbis Files (*.ogg)"); addFromPlaylist(filesToProcess[i], filenames);
filters.push_back("*.ogg");
} }
// playlist // Build the songs array
filters.push_back("Playlist Files (*.m3u;*.m3u8)"); std::vector<CMusicPlayer::CSongs> songs;
filters.push_back("*.m3u;*.m3u8"); for (i=0; i<filenames.size(); i++)
// all files
filters.push_back("All Files (*.*)");
filters.push_back("*.*");
filters.push_back("");
static wchar_t szFilter[1024] = { '\0' };
uint offset = 0;
for(uint i = 0; i < filters.size(); ++i)
{ {
wcscpy(szFilter + offset, utf8ToWide(filters[i])); // '@' in filenames are reserved for .bnp files
// and sound system fails to open such file
if (filenames[i].find("@") != string::npos)
{
nlwarning("Ignore media file containing '@' in name: '%s'", filenames[i].c_str());
continue;
}
// move offset to string length + 1 for \0 CMusicPlayer::CSongs song;
offset += filters[i].length() + 1; song.Filename = filenames[i];
SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title);
songs.push_back (song);
} }
// Filename buffer MusicPlayer.playSongs(songs);
wchar_t buffer[1024];
buffer[0]=0;
OPENFILENAMEW ofn;
memset (&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = Driver ? Driver->getDisplay():NULL;
ofn.hInstance = HInstance;
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 0;
ofn.lpstrFile = buffer;
ofn.nMaxFile = sizeof(buffer);
ofn.lpstrTitle = (wchar_t*)NLMISC::CI18N::get("uiPlaySongs").c_str();
ofn.Flags = OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT|OFN_ENABLESIZING|OFN_EXPLORER;
if (Driver)
Driver->beginDialogMode();
if (GetOpenFileNameW (&ofn))
{
bool useUtf8 = false;
// Skip the directory name
const wchar_t *bufferPtr = buffer;
// Multi filename ?
string path;
if (ofn.nFileOffset>wcslen(buffer))
{
// Backup the path and point to the next filename
path = wideToUtf8(buffer);
path += "\\";
bufferPtr += wcslen(bufferPtr)+1;
}
// Get selected files and playlists
std::vector<std::string> filenames;
std::vector<std::string> playlists;
while (*bufferPtr)
{
// Concat the directory name with the filename
std::string ext = toLower(CFile::getExtension(wideToUtf8(bufferPtr)));
if (ext == "m3u" || ext == "m3u8")
{
playlists.push_back (path + wideToUtf8(bufferPtr));
}
else
{
filenames.push_back (path + wideToUtf8(bufferPtr));
}
bufferPtr += wcslen(bufferPtr) + 1;
}
// Sort songs by filename
sort (filenames.begin(), filenames.end());
static uint8 utf8Header[] = { 0xefu, 0xbbu, 0xbfu };
// Add playlist
uint i;
for (i=0; i<playlists.size(); i++)
{
// Get the path of the playlist
string basePlaylist = CFile::getPath (playlists[i]);
FILE *file = nlfopen (playlists[i], "r");
bool useUtf8 = CFile::getExtension(playlists[i]) == "m3u8";
if (file)
{
char line[512];
while (fgets (line, 512, file))
{
// Not a comment line
string lineStr = trim(std::string(line));
// id a UTF-8 BOM header is present, parse as UTF-8
if (!useUtf8 && lineStr.length() >= 3 && memcmp(line, utf8Header, 3) == 0)
useUtf8 = true;
if (!useUtf8) lineStr = ucstring(line).toUtf8();
if (lineStr[0] != '#')
filenames.push_back (CPath::makePathAbsolute(lineStr, basePlaylist));
}
fclose (file);
}
}
// Build the songs array
std::vector<CMusicPlayer::CSongs> songs;
for (i=0; i<filenames.size(); i++)
{
CMusicPlayer::CSongs song;
song.Filename = filenames[i];
SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title);
songs.push_back (song);
}
MusicPlayer.playSongs(songs);
}
if (Driver)
Driver->endDialogMode();
// Restore mouse
InitMouseWithCursor (wasHardware);
Driver->showCursor (wasHardware);
// Restore current path
CPath::setCurrentPath (currentPath.c_str());
#endif // NL_OS_WINDOWS
} }
else if (Params == "previous") else if (Params == "previous")
MusicPlayer.previous(); MusicPlayer.previous();