// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#include "stdpch.h"
#include "music_player.h"
#include "nel/gui/action_handler.h"
#include "../input.h"
#include "../sound_manager.h"
#include "interface_manager.h"
using namespace std;
using namespace NLMISC;
using namespace NL3D;
#ifdef NL_OS_WINDOWS
extern HINSTANCE HInstance;
#endif
extern UDriver *Driver;
CMusicPlayer MusicPlayer;
// ***************************************************************************
CMusicPlayer::CMusicPlayer ()
{
_CurrentSong = 0;
_State = Stopped;
}
// ***************************************************************************
void CMusicPlayer::playSongs (const std::vector &songs)
{
_Songs = songs;
_CurrentSong = 0;
// If pause, stop, else play will resume
if (_State == Paused)
_State = Stopped;
play ();
}
// ***************************************************************************
void CMusicPlayer::play ()
{
if(!SoundMngr)
return;
if (!_Songs.empty())
{
nlassert (_CurrentSong<_Songs.size());
/* If the player is paused, resume, else, play the current song */
if (_State == Paused)
SoundMngr->resumeMusic();
else
SoundMngr->playMusic(_Songs[_CurrentSong].Filename, 0, true, false, false);
_State = Playing;
/* Show the song title */
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewText *pVT = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text"));
if (pVT)
pVT->setText (ucstring::makeFromUtf8(_Songs[_CurrentSong].Title));
}
}
// ***************************************************************************
void CMusicPlayer::pause ()
{
if(!SoundMngr)
return;
// pause the music only if we are really playing (else risk to pause a background music!)
if(_State==Playing)
{
SoundMngr->pauseMusic();
_State = Paused;
}
}
// ***************************************************************************
void CMusicPlayer::stop ()
{
if(!SoundMngr)
return;
// stop the music only if we are really playing (else risk to stop a background music!)
SoundMngr->stopMusic(0);
_State = Stopped;
}
// ***************************************************************************
void CMusicPlayer::previous ()
{
if (!_Songs.empty())
{
// Point the previous song
if (_CurrentSong == 0)
_CurrentSong = (uint)_Songs.size()-1;
else
_CurrentSong--;
play ();
}
}
// ***************************************************************************
void CMusicPlayer::next ()
{
if (!_Songs.empty())
{
_CurrentSong++;
_CurrentSong%=_Songs.size();
play ();
}
}
// ***************************************************************************
void CMusicPlayer::update ()
{
if(!SoundMngr)
return;
if (_State == Playing)
{
if (SoundMngr->isMusicEnded ())
{
// Point the next song
_CurrentSong++;
_CurrentSong%=_Songs.size();
// End of the playlist ?
if (_CurrentSong != 0)
{
// No, play the next song
play ();
}
else
{
SoundMngr->stopMusic(0);
_State = Stopped;
}
}
}
}
// ***************************************************************************
class CMusicPlayerPlaySongs: public IActionHandler
{
public:
virtual void execute(CCtrlBase * /* pCaller */, const string &Params)
{
if(!SoundMngr)
return;
if (Params == "play_songs")
{
std::vector extensions;
SoundMngr->getMixer()->getMusicExtensions(extensions);
// no format supported
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);
if (false) //supportUnicode())
{
}
else
{
bool oggSupported = false;
bool mp3Supported = false;
for(uint i = 0; i < extensions.size(); ++i)
{
if (extensions[i] == "ogg")
{
oggSupported = true;
}
else if (extensions[i] == "mp3")
{
mp3Supported = true;
}
}
std::vector filters;
// supported formats
filters.push_back("All Supported Files");
std::string filter;
if (mp3Supported) filter += "*.mp3;*.mp2;*.mp1;";
if (oggSupported) filter += "*.ogg;";
filter += "*.m3u";
filters.push_back(filter);
// mp3 format
if (mp3Supported)
{
filters.push_back("MPEG Audio Files (*.mp3;*.mp2;*.mp1)");
filters.push_back("*.mp3;*.mp2;*.mp1");
}
// ogg format
if (oggSupported)
{
filters.push_back("Vorbis Files (*.ogg)");
filters.push_back("*.ogg");
}
// playlist
filters.push_back("Playlist Files (*.m3u)");
filters.push_back("*.m3u");
// all files
filters.push_back("All Files (*.*)");
filters.push_back("*.*");
filters.push_back("");
static char szFilter[1024] = { '\0' };
uint offset = 0;
for(uint i = 0; i < filters.size(); ++i)
{
strcpy(szFilter + offset, filters[i].c_str());
// move offset to string length + 1 for \0
offset += filters[i].length() + 1;
}
// Filename buffer
char buffer[65535];
buffer[0]=0;
OPENFILENAME 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 = "Play songs";
ofn.Flags = OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT|OFN_ENABLESIZING|OFN_EXPLORER;
if (Driver)
Driver->beginDialogMode();
if (GetOpenFileName (&ofn))
{
// Skip the directory name
const char *bufferPtr = buffer;
// Multi filename ?
string path;
if (ofn.nFileOffset>strlen(buffer))
{
// Backup the path and point to the next filename
path = buffer;
path += "\\";
bufferPtr+=strlen(bufferPtr)+1;
}
// Get selected files and playlists
std::vector filenames;
std::vector playlists;
while (*bufferPtr)
{
// Concat the directory name with the filename
if (toLower(CFile::getExtension(bufferPtr)) == "m3u")
playlists.push_back (path+bufferPtr);
else
filenames.push_back (path+bufferPtr);
bufferPtr+=strlen(bufferPtr)+1;
}
// Sort songs by filename
sort (filenames.begin(), filenames.end());
// Add playlist
uint i;
for (i=0; i songs;
for (i=0; igetMixer()->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")
MusicPlayer.previous();
else if (Params == "play")
MusicPlayer.play();
else if (Params == "pause")
MusicPlayer.pause();
else if (Params == "next")
MusicPlayer.next();
else
{
string volume = getParam(Params, "volume");
if (!volume.empty())
{
CInterfaceExprValue result;
if (CInterfaceExpr::eval (volume, result))
{
if (result.toDouble ())
{
float value = (float)result.getDouble() / 255.f;
clamp (value, 0, 1);
SoundMngr->setUserMusicVolume (value);
}
}
}
}
}
};
REGISTER_ACTION_HANDLER( CMusicPlayerPlaySongs, "music_player");