From 5bddfcfb224963e648ff853e6fdf963abcab9157 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 17 Apr 2020 11:49:21 +0300 Subject: [PATCH 1/7] Fixed: Audio decoder getMusicInfo/getSongTitle needs to be thread safe --- .../include/nel/sound/driver/sound_driver.h | 2 +- code/nel/src/sound/audio_decoder.cpp | 11 ++++----- .../sound/driver/fmod/sound_driver_fmod.cpp | 24 ++++--------------- .../src/sound/driver/fmod/sound_driver_fmod.h | 2 +- 4 files changed, 11 insertions(+), 28 deletions(-) diff --git a/code/nel/include/nel/sound/driver/sound_driver.h b/code/nel/include/nel/sound/driver/sound_driver.h index 1fba9c887..9c758487a 100644 --- a/code/nel/include/nel/sound/driver/sound_driver.h +++ b/code/nel/include/nel/sound/driver/sound_driver.h @@ -191,7 +191,7 @@ public: /// Create a native music channel, only supported by the FMod driver. virtual IMusicChannel *createMusicChannel() { return NULL; } /** Get music info. Returns false if the song is not found or the function is not implemented. - * \param filepath path to file, CPath::lookup done by driver + * \param filepath full path to file * \param artist returns the song artist (empty if not available) * \param title returns the title (empty if not available) */ diff --git a/code/nel/src/sound/audio_decoder.cpp b/code/nel/src/sound/audio_decoder.cpp index ac7745721..1314cd448 100644 --- a/code/nel/src/sound/audio_decoder.cpp +++ b/code/nel/src/sound/audio_decoder.cpp @@ -116,10 +116,9 @@ IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &type, NLMISC bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, std::string &title, float &length) { - std::string lookup = CPath::lookup(filepath, false); - if (lookup.empty()) + if (filepath.empty() || !CFile::fileExists(filepath)) { - nlwarning("Music file %s does not exist!", filepath.c_str()); + nlwarning("Music file '%s' does not exist!", filepath.c_str()); return false; } @@ -127,7 +126,7 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st CIFile ifile; ifile.setCacheFileOnOpen(false); ifile.allowBNPCacheFileOnOpen(false); - if (ifile.open(lookup)) + if (ifile.open(filepath)) return CAudioDecoderFfmpeg::getInfo(&ifile, artist, title, length); #else std::string type = CFile::getExtension(filepath); @@ -138,7 +137,7 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st CIFile ifile; ifile.setCacheFileOnOpen(false); ifile.allowBNPCacheFileOnOpen(false); - if (ifile.open(lookup)) + if (ifile.open(filepath)) return CAudioDecoderVorbis::getInfo(&ifile, artist, title, length); nlwarning("Unable to open: '%s'", filepath.c_str()); @@ -149,7 +148,7 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st CIFile ifile; ifile.setCacheFileOnOpen(false); ifile.allowBNPCacheFileOnOpen(false); - if (ifile.open(lookup)) + if (ifile.open(filepath)) return CAudioDecoderMP3::getInfo(&ifile, artist, title, length); nlwarning("Unable to open: '%s'", filepath.c_str()); diff --git a/code/nel/src/sound/driver/fmod/sound_driver_fmod.cpp b/code/nel/src/sound/driver/fmod/sound_driver_fmod.cpp index d98aa600f..2b250a1d3 100644 --- a/code/nel/src/sound/driver/fmod/sound_driver_fmod.cpp +++ b/code/nel/src/sound/driver/fmod/sound_driver_fmod.cpp @@ -496,36 +496,20 @@ bool getTag (std::string &result, const char *tag, FSOUND_STREAM *stream) } /** Get music info. Returns false if the song is not found or the function is not implemented. - * \param filepath path to file, CPath::lookup done by driver + * \param filepath full path to file * \param artist returns the song artist (empty if not available) * \param title returns the title (empty if not available) */ bool CSoundDriverFMod::getMusicInfo(const std::string &filepath, std::string &artist, std::string &title, float &length) { - /* Open a stream, get the tag if it exists, close the stream */ - string pathName = CPath::lookup(filepath, false); - uint32 fileOffset = 0, fileSize = 0; - if (pathName.empty()) + if (filepath.empty() || !CFile::fileExists(filepath)) { nlwarning("NLSOUND FMod Driver: Music file %s not found!", filepath.c_str()); return false; } - // if the file is in a bnp - if (pathName.find('@') != string::npos) - { - if (CBigFile::getInstance().getFileInfo(pathName, fileSize, fileOffset)) - { - // set pathname to bnp - pathName = pathName.substr(0, pathName.find('@')); - } - else - { - nlwarning("NLSOUND FMod Driver: BNP BROKEN"); - return false; - } - } - FSOUND_STREAM *stream = FSOUND_Stream_Open((const char *)CPath::lookup(filepath, false).c_str(), FSOUND_2D, (sint)fileOffset, (sint)fileSize); + uint32 fileOffset = 0, fileSize = 0; + FSOUND_STREAM *stream = FSOUND_Stream_Open(filepath.c_str(), FSOUND_2D, (sint)fileOffset, (sint)fileSize); if (stream) { getTag(artist, "ARTIST", stream); diff --git a/code/nel/src/sound/driver/fmod/sound_driver_fmod.h b/code/nel/src/sound/driver/fmod/sound_driver_fmod.h index db82cde6e..73d3b8673 100644 --- a/code/nel/src/sound/driver/fmod/sound_driver_fmod.h +++ b/code/nel/src/sound/driver/fmod/sound_driver_fmod.h @@ -112,7 +112,7 @@ public: virtual IMusicChannel *createMusicChannel(); /** Get music info. Returns false if the song is not found or the function is not implemented. - * \param filepath path to file, CPath::lookup done by driver + * \param filepath full path to file * \param artist returns the song artist (empty if not available) * \param title returns the title (empty if not available) */ From 52d6f89e1e6036640221af8fa7fca9e3ba8445c4 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 17 Apr 2020 13:29:27 +0300 Subject: [PATCH 2/7] Fixed: Clear song info when all songs are done playing. --- .../client/src/interface_v3/music_player.cpp | 60 +++++++++++++------ .../client/src/interface_v3/music_player.h | 6 ++ 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/music_player.cpp b/code/ryzom/client/src/interface_v3/music_player.cpp index 2f02352fb..98bbd5299 100644 --- a/code/ryzom/client/src/interface_v3/music_player.cpp +++ b/code/ryzom/client/src/interface_v3/music_player.cpp @@ -174,28 +174,30 @@ void CMusicPlayer::playSongs (const std::vector &filenames) // If pause, stop, else play will resume if (_State == Paused || _Songs.empty()) - _State = Stopped; + stop(); // get song title/duration using worker thread MusicPlayerWorker.getSongsInfo(filenames); } // *************************************************************************** -void CMusicPlayer::updatePlaylist(sint prevIndex) +void CMusicPlayer::updatePlaylist(uint index, bool state) { - CInterfaceElement *pIE; - std::string rowId; + if (index >= _Songs.size()) return; + + std::string rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, index); + CInterfaceElement *pIE = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(rowId)); + if (pIE) pIE->setActive(state); +} +void CMusicPlayer::updatePlaylist(sint prevIndex) +{ if (prevIndex >= 0 && prevIndex < _Songs.size()) { - rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, prevIndex); - pIE = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(rowId)); - if (pIE) pIE->setActive(false); + updatePlaylist(prevIndex, false); } - rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, _CurrentSongIndex); - pIE = dynamic_cast(CWidgetManager::getInstance()->getElementFromId(rowId)); - if (pIE) pIE->setActive(true); + updatePlaylist(_CurrentSongIndex, true); } // *************************************************************************** @@ -361,7 +363,7 @@ void CMusicPlayer::play (sint index) if (_Songs.empty()) { - _State = Stopped; + stop(); return; } @@ -437,6 +439,8 @@ void CMusicPlayer::stop () _PlayStart = 0; _PauseTime = 0; + clearPlayingInfo(); + NLGUI::CDBManager::getInstance()->getDbProp("UI:TEMP:MP3_PLAYING")->setValueBool(false); } @@ -472,12 +476,31 @@ void CMusicPlayer::next () } // *************************************************************************** +void CMusicPlayer::updatePlayingInfo(const std::string info) +{ + CViewText *pVT = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text")); + if (pVT) + { + pVT->setText(ucstring::makeFromUtf8(info)); + } +} + +// *************************************************************************** +void CMusicPlayer::clearPlayingInfo() +{ + updatePlayingInfo(""); +} +// *************************************************************************** void CMusicPlayer::update () { if(!SoundMngr) { - _State = Stopped; + if (_State != Stopped) + { + _State = Stopped; + clearPlayingInfo(); + } return; } @@ -488,8 +511,6 @@ void CMusicPlayer::update () if (_State == Playing) { - CViewText *pVT = dynamic_cast(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text")); - if (pVT) { TTime dur = (CTime::getLocalTime() - _PlayStart) / 1000; uint min = (dur / 60) % 60; @@ -499,7 +520,7 @@ void CMusicPlayer::update () std::string title(toString("%02d:%02d", min, sec)); if (hour > 0) title = toString("%02d:", hour) + title; title += " " + _CurrentSong.Title; - pVT->setText(ucstring::makeFromUtf8(title)); + updatePlayingInfo(title); } if (SoundMngr->isMusicEnded ()) @@ -520,8 +541,13 @@ void CMusicPlayer::update () } else { - SoundMngr->stopMusic(0); - _State = Stopped; + // remove active highlight from playlist + updatePlaylist(_CurrentSongIndex, false); + + stop(); + + // restart from top on next 'play' + _CurrentSongIndex = 0; } } } diff --git a/code/ryzom/client/src/interface_v3/music_player.h b/code/ryzom/client/src/interface_v3/music_player.h index 1932591e3..febfde719 100644 --- a/code/ryzom/client/src/interface_v3/music_player.h +++ b/code/ryzom/client/src/interface_v3/music_player.h @@ -62,6 +62,10 @@ public: void update (); + // update currently playing song info/duration on main gui + void updatePlayingInfo(const std::string info); + void clearPlayingInfo(); + bool isRepeatEnabled() const; bool isShuffleEnabled() const; @@ -71,6 +75,8 @@ public: void shuffleAndRebuildPlaylist(); // Update playlist active row void updatePlaylist(sint prevIndex = -1); + // set/remove playlist highlight + void updatePlaylist(uint index, bool state); // Update single song title/duration on _Songs and on playlist void updateSong(const CSongs &song); From 6993a2731faa99fe2c491e253c36d404cec40b8b Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 18 Apr 2020 09:31:29 +0300 Subject: [PATCH 3/7] Changed: SHow no-files text if there is no songs in playlist --- code/ryzom/client/src/interface_v3/music_player.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/interface_v3/music_player.cpp b/code/ryzom/client/src/interface_v3/music_player.cpp index 98bbd5299..6c94fa2cf 100644 --- a/code/ryzom/client/src/interface_v3/music_player.cpp +++ b/code/ryzom/client/src/interface_v3/music_player.cpp @@ -488,7 +488,14 @@ void CMusicPlayer::updatePlayingInfo(const std::string info) // *************************************************************************** void CMusicPlayer::clearPlayingInfo() { - updatePlayingInfo(""); + if (_Songs.empty()) + { + updatePlayingInfo(CI18N::get("uiNoFiles").toUtf8()); + } + else + { + updatePlayingInfo(""); + } } // *************************************************************************** From bde8d008d153e6d0f9e235f6665c7324d6dd2faf Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 18 Apr 2020 10:50:20 +0300 Subject: [PATCH 4/7] Fixed: Crash on switching chars, logout --- code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index 3d6c58dcd..56727f6d4 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -567,6 +567,11 @@ CDBCtrlSheet::~CDBCtrlSheet() Driver->deleteTextureFile(_GuildSymb); _GuildSymb = NULL; } + if (_RegenText) + { + delete _RegenText; + _RegenText = NULL; + } // ensure erase static if(this==_CurrMenuSheet) _CurrMenuSheet = NULL; From 36187626a9a87eaa3e700c72ee0c6bbac24e6439 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 18 Apr 2020 11:47:28 +0300 Subject: [PATCH 5/7] Fixed: Restore playlist after charselect --- code/ryzom/client/src/interface_v3/interface_manager.cpp | 4 ++++ code/ryzom/client/src/release.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index f8637bff3..e81785ea8 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -1044,6 +1044,10 @@ void CInterfaceManager::initInGame() gc->setTarget(gc->getSavedTarget()); } + // rebuild mp3 player playlist if user reselected a char (songs are already scanned) + CAHManager::getInstance()->runActionHandler("music_player", NULL, "update_playlist"); + CAHManager::getInstance()->runActionHandler("music_player", NULL, "stop"); + CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHATLOG_STATE", false); if (node) { diff --git a/code/ryzom/client/src/release.cpp b/code/ryzom/client/src/release.cpp index 0477acce9..889bcee11 100644 --- a/code/ryzom/client/src/release.cpp +++ b/code/ryzom/client/src/release.cpp @@ -240,8 +240,8 @@ void releaseMainLoopReselect() // alredy called from farTPMainLoop() // --R2::getEditor().autoConfigRelease(IsInRingSession); - // Pause any user played music - MusicPlayer.pause(); + // stop any user played music + MusicPlayer.stop(); // only really needed at exit // --STRING_MANAGER::CStringManagerClient::instance()->flushStringCache(); @@ -390,8 +390,8 @@ void releaseMainLoop(bool closeConnection) // Release R2 editor if applicable R2::getEditor().autoConfigRelease(IsInRingSession); - // Pause any user played music - MusicPlayer.pause(); + // stop any user played music + MusicPlayer.stop(); // flush the server string cache STRING_MANAGER::CStringManagerClient::instance()->flushStringCache(); From 3da2f45363a7d4c23db822ff5e99e75377a7c9e8 Mon Sep 17 00:00:00 2001 From: Ulukyn Date: Mon, 4 May 2020 17:19:24 +0200 Subject: [PATCH 6/7] Added: Remove ambiance ans shininess to SE shapes. Add seasons texture set --- code/nel/src/misc/bitmap.cpp | 110 +++++++++--------- .../client/src/interface_v3/lua_ihm_ryzom.cpp | 19 ++- 2 files changed, 73 insertions(+), 56 deletions(-) diff --git a/code/nel/src/misc/bitmap.cpp b/code/nel/src/misc/bitmap.cpp index 015a9c4c4..c21b30fb7 100644 --- a/code/nel/src/misc/bitmap.cpp +++ b/code/nel/src/misc/bitmap.cpp @@ -3269,77 +3269,79 @@ CRGBAF CBitmap::getColor (float x, float y) const uint32 i; + bool isValid = true; for (i = 0; i < 4; ++i) { - nlassert (nX[i] >= 0); - nlassert (nY[i] >= 0 ); - nlassert (nX[i] < nWidth); - nlassert (nY[i] < nHeight); + if (nX[i] < 0 || nY[i] < 0 || nX[i] >= nWidth || nY[i] >= nHeight) + isValid = false; } - // Decimal part of (x,y) - x = x - (float)nX[0]; - y = y - (float)nY[0]; - - switch (this->PixelFormat) + if (isValid) { - case RGBA: - case DXTC1: - case DXTC1Alpha: - case DXTC3: - case DXTC5: - { - CRGBAF finalVal; - CRGBA val[4]; + // Decimal part of (x,y) + x = x - (float)nX[0]; + y = y - (float)nY[0]; - if (this->PixelFormat == RGBA) + switch (this->PixelFormat) + { + case RGBA: + case DXTC1: + case DXTC1Alpha: + case DXTC3: + case DXTC5: { - for (i = 0; i < 4; ++i) + CRGBAF finalVal; + CRGBA val[4]; + + if (this->PixelFormat == RGBA) { - val[i] = CRGBA (rBitmap[(nX[i]+nY[i]*nWidth)*4+0], - rBitmap[(nX[i]+nY[i]*nWidth)*4+1], - rBitmap[(nX[i]+nY[i]*nWidth)*4+2], - rBitmap[(nX[i]+nY[i]*nWidth)*4+3]); + for (i = 0; i < 4; ++i) + { + val[i] = CRGBA (rBitmap[(nX[i]+nY[i]*nWidth)*4+0], + rBitmap[(nX[i]+nY[i]*nWidth)*4+1], + rBitmap[(nX[i]+nY[i]*nWidth)*4+2], + rBitmap[(nX[i]+nY[i]*nWidth)*4+3]); + } } - } - else - { - // slower version : get from DXT - for (i = 0; i < 4; ++i) + else { - val[i] = getPixelColor(nX[i], nY[i]); + // slower version : get from DXT + for (i = 0; i < 4; ++i) + { + val[i] = getPixelColor(nX[i], nY[i]); + } } - } - finalVal.R = getColorInterp (x, y, val[0].R, val[1].R, val[2].R, val[3].R); - finalVal.G = getColorInterp (x, y, val[0].G, val[1].G, val[2].G, val[3].G); - finalVal.B = getColorInterp (x, y, val[0].B, val[1].B, val[2].B, val[3].B); - finalVal.A = getColorInterp (x, y, val[0].A, val[1].A, val[2].A, val[3].A); - finalVal /= 255.f; + finalVal.R = getColorInterp (x, y, val[0].R, val[1].R, val[2].R, val[3].R); + finalVal.G = getColorInterp (x, y, val[0].G, val[1].G, val[2].G, val[3].G); + finalVal.B = getColorInterp (x, y, val[0].B, val[1].B, val[2].B, val[3].B); + finalVal.A = getColorInterp (x, y, val[0].A, val[1].A, val[2].A, val[3].A); + finalVal /= 255.f; - return finalVal; - } - break; - case Alpha: - case Luminance: - { + return finalVal; + } + break; + case Alpha: + case Luminance: + { - float finalVal; - float val[4]; + float finalVal; + float val[4]; - for (i = 0; i < 4; ++i) - val[i] = rBitmap[(nX[i]+nY[i]*nWidth)]; + for (i = 0; i < 4; ++i) + val[i] = rBitmap[(nX[i]+nY[i]*nWidth)]; - finalVal = getColorInterp (x, y, val[0], val[1], val[2], val[3]); - finalVal /= 255.f; + finalVal = getColorInterp (x, y, val[0], val[1], val[2], val[3]); + finalVal /= 255.f; - if (this->PixelFormat == Alpha) - return CRGBAF (1.f, 1.f, 1.f, finalVal); - else // Luminance - return CRGBAF (finalVal, finalVal, finalVal, 1.f); + if (this->PixelFormat == Alpha) + return CRGBAF (1.f, 1.f, 1.f, finalVal); + else // Luminance + return CRGBAF (finalVal, finalVal, finalVal, 1.f); + } + break; + default: break; } - break; - default: break; } return CRGBAF (0.0f, 0.0f, 0.0f, 0.0f); @@ -3626,7 +3628,7 @@ void CBitmap::loadSize(NLMISC::IStream &f, uint32 &retWidth, uint32 &retHeight) { uint8 imagePrecision = 0; // sample precision uint32 imageSize = 0; // width and height - f.serial(imagePrecision); + f.serial(imagePrecision); f.serial(imageSize); NLMISC_BSWAP32(imageSize); diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp index ac8d7dde8..8aa7af585 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp @@ -2298,13 +2298,28 @@ int CLuaIHMRyzom::addShape(CLuaState &ls) if(!instance.empty()) { + + if (texture == "#season#" || texture.empty()) + { + uint8 selectedTextureSet = (uint8)::computeCurrSeason(); + instance.selectTextureSet(selectedTextureSet); + texture = ""; + } + else if (texture[0] == '#') + { + uint8 selectedTextureSet; + fromString(texture.substr(1), selectedTextureSet); + instance.selectTextureSet(selectedTextureSet); + texture = ""; + } + for(uint j=0;j Date: Wed, 6 May 2020 17:43:51 +0300 Subject: [PATCH 7/7] Fixed: Calling stop on music player should not affect background music. --- code/ryzom/client/src/interface_v3/music_player.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/ryzom/client/src/interface_v3/music_player.cpp b/code/ryzom/client/src/interface_v3/music_player.cpp index 6c94fa2cf..56f97b554 100644 --- a/code/ryzom/client/src/interface_v3/music_player.cpp +++ b/code/ryzom/client/src/interface_v3/music_player.cpp @@ -434,7 +434,9 @@ void CMusicPlayer::stop () return; // stop the music only if we are really playing (else risk to stop a background music!) - SoundMngr->stopMusic(0); + if (_State != Stopped) + SoundMngr->stopMusic(0); + _State = Stopped; _PlayStart = 0; _PauseTime = 0;