// 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); 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"); // TODO: translate std::string filter; 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)"); 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;*.m3u8)"); filters.push_back("*.m3u;*.m3u8"); // 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])); // move offset to string length + 1 for \0 offset += filters[i].length() + 1; } // Filename buffer 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 filenames; std::vector 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= 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 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");