Merge with develop

--HG--
branch : compatibility-develop
hg/compatibility-develop
Nimetu 6 years ago
commit e4ac3748e9

@ -101,6 +101,9 @@ namespace NLGUI
// test is a group is a direct child of this interface group // test is a group is a direct child of this interface group
bool isChildGroup(const CInterfaceGroup *group) const; bool isChildGroup(const CInterfaceGroup *group) const;
// test is x,y is inside last draw clip aread
bool isInViewport(sint32 x, sint32 y) const;
virtual bool isWindowUnder (sint32 x, sint32 y); // Virtual for menu that is not square virtual bool isWindowUnder (sint32 x, sint32 y); // Virtual for menu that is not square
CInterfaceGroup *getGroupUnder (sint32 x, sint32 y); CInterfaceGroup *getGroupUnder (sint32 x, sint32 y);
virtual bool getViewsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector<CViewBase*> &vVB); // Return true if x,y under the group virtual bool getViewsUnder (sint32 x, sint32 y, sint32 clipX, sint32 clipY, sint32 clipW, sint32 clipH, std::vector<CViewBase*> &vVB); // Return true if x,y under the group
@ -341,8 +344,13 @@ namespace NLGUI
void alignElements(); void alignElements();
protected: protected:
/// Last clip area cached from draw call
sint32 _LastClipX;
sint32 _LastClipY;
sint32 _LastClipW;
sint32 _LastClipH;
void makeNewClip (sint32 &oldClipX, sint32 &oldClipY, sint32 &oldClipW, sint32 &oldClipH); void makeNewClip (sint32 &oldClipX, sint32 &oldClipY, sint32 &oldClipW, sint32 &oldClipH, bool drawing = false);
void restoreClip (sint32 oldSciX, sint32 oldSciY, sint32 oldSciW, sint32 oldSciH); void restoreClip (sint32 oldSciX, sint32 oldSciY, sint32 oldSciW, sint32 oldSciH);
// Compute clip contribution for current window, and a previous clipping rectangle. This doesn't change the clip window in the driver. // Compute clip contribution for current window, and a previous clipping rectangle. This doesn't change the clip window in the driver.

@ -100,6 +100,7 @@ private:
IAudioDecoder *m_AudioDecoder; IAudioDecoder *m_AudioDecoder;
bool m_Paused; bool m_Paused;
bool m_DecodingEnded;
}; /* class CStreamFileSource */ }; /* class CStreamFileSource */

@ -899,7 +899,7 @@ namespace NLGUI
} }
if (!(_SizeRef & 2)) if (!(_SizeRef & 2))
{ {
_H= _BmpH; _H= max(_BmpH, _ViewText->getH());
} }
CViewBase::updateCoords(); CViewBase::updateCoords();

@ -77,6 +77,11 @@ namespace NLGUI
_LUAEnvTableCreated= false; _LUAEnvTableCreated= false;
_DepthForZSort= 0.f; _DepthForZSort= 0.f;
_LastClipX = 0;
_LastClipY = 0;
_LastClipW = 0;
_LastClipH = 0;
#ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
CInterfaceManager::getInstance()->DebugTrackGroupsCreated( this ); CInterfaceManager::getInstance()->DebugTrackGroupsCreated( this );
#endif #endif
@ -1254,7 +1259,8 @@ namespace NLGUI
{ {
const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event; const NLGUI::CEventDescriptorMouse &eventDesc = (const NLGUI::CEventDescriptorMouse &)event;
if (!isIn(eventDesc.getX(), eventDesc.getY())) // group might be partially hidden (scolling) so test against last visible area
if (!isInViewport(eventDesc.getX(), eventDesc.getY()))
return false; return false;
bool taken = false; bool taken = false;
@ -1299,7 +1305,6 @@ namespace NLGUI
} }
if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel) if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel)
{ {
// handle the Mouse Wheel only if interesting
if (_H>_MaxH) if (_H>_MaxH)
{ {
CInterfaceGroup *currParent = _Parent; CInterfaceGroup *currParent = _Parent;
@ -1329,7 +1334,7 @@ namespace NLGUI
void CInterfaceGroup::draw () void CInterfaceGroup::draw ()
{ {
sint32 oldSciX, oldSciY, oldSciW, oldSciH; sint32 oldSciX, oldSciY, oldSciW, oldSciH;
makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH); makeNewClip (oldSciX, oldSciY, oldSciW, oldSciH, true);
// Display sons only if not total clipped // Display sons only if not total clipped
CViewRenderer &rVR = *CViewRenderer::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance();
@ -1718,6 +1723,16 @@ namespace NLGUI
(y <= (_YReal + _HReal))); (y <= (_YReal + _HReal)));
} }
// ------------------------------------------------------------------------------------------------
bool CInterfaceGroup::isInViewport(sint32 x, sint32 y) const
{
return (
(x > _LastClipX) &&
(x < (_LastClipX + _LastClipW))&&
(y > _LastClipY) &&
(y < (_LastClipY + _LastClipH)));
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
CInterfaceGroup* CInterfaceGroup::getGroupUnder (sint32 x, sint32 y) CInterfaceGroup* CInterfaceGroup::getGroupUnder (sint32 x, sint32 y)
{ {
@ -1976,11 +1991,10 @@ namespace NLGUI
newSciYDest = newSciY; newSciYDest = newSciY;
newSciWDest = newSciW/* - _MarginLeft*/; newSciWDest = newSciW/* - _MarginLeft*/;
newSciHDest = newSciH; newSciHDest = newSciH;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void CInterfaceGroup::makeNewClip (sint32 &oldSciX, sint32 &oldSciY, sint32 &oldSciW, sint32 &oldSciH) void CInterfaceGroup::makeNewClip (sint32 &oldSciX, sint32 &oldSciY, sint32 &oldSciW, sint32 &oldSciH, bool drawing)
{ {
CViewRenderer &rVR = *CViewRenderer::getInstance(); CViewRenderer &rVR = *CViewRenderer::getInstance();
rVR.getClipWindow (oldSciX, oldSciY, oldSciW, oldSciH); rVR.getClipWindow (oldSciX, oldSciY, oldSciW, oldSciH);
@ -1988,6 +2002,14 @@ namespace NLGUI
sint32 newSciX, newSciY, newSciW, newSciH; sint32 newSciX, newSciY, newSciW, newSciH;
computeCurrentClipContribution(oldSciX, oldSciY, oldSciW, oldSciH, newSciX, newSciY, newSciW, newSciH); computeCurrentClipContribution(oldSciX, oldSciY, oldSciW, oldSciH, newSciX, newSciY, newSciW, newSciH);
rVR.setClipWindow (newSciX, newSciY, newSciW, newSciH); rVR.setClipWindow (newSciX, newSciY, newSciW, newSciH);
if (drawing)
{
_LastClipX = newSciX;
_LastClipY = newSciY;
_LastClipW = newSciW;
_LastClipH = newSciH;
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

@ -45,7 +45,7 @@ using namespace std;
namespace NLSOUND { namespace NLSOUND {
CStreamFileSource::CStreamFileSource(CStreamFileSound *streamFileSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController) CStreamFileSource::CStreamFileSource(CStreamFileSound *streamFileSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController)
: CStreamSource(streamFileSound, spawn, cb, cbUserParam, cluster, groupController), m_AudioDecoder(NULL), m_Paused(false) : CStreamSource(streamFileSound, spawn, cb, cbUserParam, cluster, groupController), m_AudioDecoder(NULL), m_Paused(false), m_DecodingEnded(false)
{ {
m_Thread = NLMISC::IThread::create(this); m_Thread = NLMISC::IThread::create(this);
} }
@ -244,7 +244,7 @@ void CStreamFileSource::resume()
bool CStreamFileSource::isEnded() bool CStreamFileSource::isEnded()
{ {
return (!m_Thread->isRunning() && !_Playing && !m_WaitingForPlay && !m_Paused); return m_DecodingEnded || (!m_Thread->isRunning() && !_Playing && !m_WaitingForPlay && !m_Paused);
} }
float CStreamFileSource::getLength() float CStreamFileSource::getLength()
@ -319,6 +319,7 @@ void CStreamFileSource::run()
this->getRecommendedBufferSize(samples, bytes); this->getRecommendedBufferSize(samples, bytes);
uint32 recSleep = 40; uint32 recSleep = 40;
uint32 doSleep = 10; uint32 doSleep = 10;
m_DecodingEnded = false;
while (_Playing || m_WaitingForPlay) while (_Playing || m_WaitingForPlay)
{ {
if (!m_AudioDecoder->isMusicEnded()) if (!m_AudioDecoder->isMusicEnded())
@ -369,6 +370,9 @@ void CStreamFileSource::run()
{ {
delete m_AudioDecoder; delete m_AudioDecoder;
m_AudioDecoder = NULL; m_AudioDecoder = NULL;
// _Playing cannot be used to detect play state because its required in cleanup
// Using m_AudioDecoder in isEnded() may result race condition (decoder is only created after thread is started)
m_DecodingEnded = true;
} }
// drop buffers // drop buffers
m_FreeBuffers = 3; m_FreeBuffers = 3;

@ -39,6 +39,9 @@ extern UDriver *Driver;
#define TEMPLATE_PLAYLIST_SONG "playlist_song" #define TEMPLATE_PLAYLIST_SONG "playlist_song"
#define TEMPLATE_PLAYLIST_SONG_TITLE "title" #define TEMPLATE_PLAYLIST_SONG_TITLE "title"
#define TEMPLATE_PLAYLIST_SONG_DURATION "duration" #define TEMPLATE_PLAYLIST_SONG_DURATION "duration"
// ui state
#define MP3_SAVE_SHUFFLE "UI:SAVE:MP3_SHUFFLE"
#define MP3_SAVE_REPEAT "UI:SAVE:MP3_REPEAT"
static const std::string MediaPlayerDirectory("music/"); static const std::string MediaPlayerDirectory("music/");
@ -48,8 +51,20 @@ CMusicPlayer MusicPlayer;
CMusicPlayer::CMusicPlayer () CMusicPlayer::CMusicPlayer ()
{ {
_CurrentSong = 0; _CurrentSongIndex = 0;
_State = Stopped; _State = Stopped;
_PlayStart = 0;
_PauseTime = 0;
}
bool CMusicPlayer::isRepeatEnabled() const
{
return (NLGUI::CDBManager::getInstance()->getDbProp(MP3_SAVE_REPEAT)->getValue32() == 1);
}
bool CMusicPlayer::isShuffleEnabled() const
{
return (NLGUI::CDBManager::getInstance()->getDbProp(MP3_SAVE_SHUFFLE)->getValue32() == 1);
} }
@ -59,16 +74,61 @@ void CMusicPlayer::playSongs (const std::vector<CSongs> &songs)
_Songs = songs; _Songs = songs;
// reset song index if out of bounds // reset song index if out of bounds
if (_CurrentSong > _Songs.size()) if (_CurrentSongIndex > _Songs.size())
_CurrentSong = 0; _CurrentSongIndex = 0;
if (isShuffleEnabled())
shuffleAndRebuildPlaylist();
else
rebuildPlaylist();
// If pause, stop, else play will resume
if (_State == Paused)
_State = Stopped;
}
// ***************************************************************************
void CMusicPlayer::updatePlaylist(sint prevIndex)
{
CInterfaceElement *pIE;
std::string rowId;
if (prevIndex >= 0 && prevIndex < _Songs.size())
{
rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, prevIndex);
pIE = dynamic_cast<CInterfaceElement*>(CWidgetManager::getInstance()->getElementFromId(rowId));
if (pIE) pIE->setActive(false);
}
rowId = toString("%s:s%d:bg", MP3_PLAYER_PLAYLIST_LIST, _CurrentSongIndex);
pIE = dynamic_cast<CInterfaceElement*>(CWidgetManager::getInstance()->getElementFromId(rowId));
if (pIE) pIE->setActive(true);
}
// ***************************************************************************
void CMusicPlayer::shuffleAndRebuildPlaylist()
{
std::random_shuffle(_Songs.begin(), _Songs.end());
rebuildPlaylist();
}
// ***************************************************************************
void CMusicPlayer::rebuildPlaylist()
{
CGroupList *pList = dynamic_cast<CGroupList *>(CWidgetManager::getInstance()->getElementFromId(MP3_PLAYER_PLAYLIST_LIST)); CGroupList *pList = dynamic_cast<CGroupList *>(CWidgetManager::getInstance()->getElementFromId(MP3_PLAYER_PLAYLIST_LIST));
if (pList) if (pList)
{ {
pList->clearGroups(); pList->clearGroups();
pList->setDynamicDisplaySize(true); pList->setDynamicDisplaySize(true);
bool found = _CurrentSong.Filename.empty();
for (uint i=0; i < _Songs.size(); ++i) for (uint i=0; i < _Songs.size(); ++i)
{ {
if (!found && _CurrentSong.Filename == _Songs[i].Filename)
{
found = true;
_CurrentSongIndex = i;
}
uint min = (sint32)(_Songs[i].Length / 60) % 60; uint min = (sint32)(_Songs[i].Length / 60) % 60;
uint sec = (sint32)(_Songs[i].Length) % 60; uint sec = (sint32)(_Songs[i].Length) % 60;
uint hour = _Songs[i].Length / 3600; uint hour = _Songs[i].Length / 3600;
@ -103,9 +163,7 @@ void CMusicPlayer::playSongs (const std::vector<CSongs> &songs)
pList->invalidateCoords(); pList->invalidateCoords();
} }
// If pause, stop, else play will resume updatePlaylist();
if (_State == Paused)
_State = Stopped;
} }
@ -116,31 +174,40 @@ void CMusicPlayer::play (sint index)
if(!SoundMngr) if(!SoundMngr)
return; return;
sint prevSongIndex = _CurrentSongIndex;
if (index >= 0 && index < (sint)_Songs.size()) if (index >= 0 && index < (sint)_Songs.size())
{ {
if (_State == Paused) if (_State == Paused)
{
stop(); stop();
}
_CurrentSong = index; _CurrentSongIndex = index;
_PauseTime = 0;
} }
if (!_Songs.empty()) if (!_Songs.empty())
{ {
nlassert (_CurrentSong<_Songs.size()); nlassert (_CurrentSongIndex<_Songs.size());
/* If the player is paused, resume, else, play the current song */ /* If the player is paused, resume, else, play the current song */
if (_State == Paused) if (_State == Paused)
{
SoundMngr->resumeMusic(); SoundMngr->resumeMusic();
}
else else
SoundMngr->playMusic(_Songs[_CurrentSong].Filename, 0, true, false, false); {
SoundMngr->playMusic(_Songs[_CurrentSongIndex].Filename, 0, true, false, false);
_PauseTime = 0;
}
_State = Playing; _State = Playing;
_PlayStart = CTime::getLocalTime() - _PauseTime;
/* Show the song title */ _CurrentSong = _Songs[_CurrentSongIndex];
CInterfaceManager *pIM = CInterfaceManager::getInstance();
CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text")); updatePlaylist(prevSongIndex);
if (pVT)
pVT->setText (ucstring::makeFromUtf8(_Songs[_CurrentSong].Title));
} }
} }
@ -155,6 +222,9 @@ void CMusicPlayer::pause ()
{ {
SoundMngr->pauseMusic(); SoundMngr->pauseMusic();
_State = Paused; _State = Paused;
if (_PlayStart > 0)
_PauseTime = CTime::getLocalTime() - _PlayStart;
} }
} }
@ -167,6 +237,8 @@ void CMusicPlayer::stop ()
// stop the music only if we are really playing (else risk to stop a background music!) // stop the music only if we are really playing (else risk to stop a background music!)
SoundMngr->stopMusic(0); SoundMngr->stopMusic(0);
_State = Stopped; _State = Stopped;
_PlayStart = 0;
_PauseTime = 0;
} }
// *************************************************************************** // ***************************************************************************
@ -176,12 +248,13 @@ void CMusicPlayer::previous ()
if (!_Songs.empty()) if (!_Songs.empty())
{ {
// Point the previous song // Point the previous song
if (_CurrentSong == 0) sint index;
_CurrentSong = (uint)_Songs.size()-1; if (_CurrentSongIndex == 0)
index = (uint)_Songs.size()-1;
else else
_CurrentSong--; index = _CurrentSongIndex-1;
play (); play(index);
} }
} }
@ -191,9 +264,11 @@ void CMusicPlayer::next ()
{ {
if (!_Songs.empty()) if (!_Songs.empty())
{ {
_CurrentSong++; sint index = _CurrentSongIndex+1;
_CurrentSong%=_Songs.size(); if (index == _Songs.size())
play (); index = 0;
play(index);
} }
} }
@ -205,17 +280,30 @@ void CMusicPlayer::update ()
return; return;
if (_State == Playing) if (_State == Playing)
{ {
if (SoundMngr->isMusicEnded ()) CViewText *pVT = dynamic_cast<CViewText*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:mp3_player:screen:text"));
if (pVT)
{ {
// Point the next song TTime dur = (CTime::getLocalTime() - _PlayStart) / 1000;
_CurrentSong++; std::string title;
_CurrentSong%=_Songs.size(); title = toString("%02d:%02d %s", dur / 60, dur % 60, _CurrentSong.Title.c_str());
pVT->setText(ucstring::makeFromUtf8(title));
}
// End of the playlist ? if (SoundMngr->isMusicEnded ())
if (_CurrentSong != 0) {
// select next song from playlist
sint index = _CurrentSongIndex + 1;
if (isRepeatEnabled() || index < _Songs.size())
{ {
// No, play the next song if (index == _Songs.size())
play (); {
index = 0;
if (isShuffleEnabled())
shuffleAndRebuildPlaylist();
}
play(index);
} }
else else
{ {
@ -361,11 +449,19 @@ public:
CMusicPlayer::CSongs song; CMusicPlayer::CSongs song;
song.Filename = filenames[i]; song.Filename = filenames[i];
SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title, song.Length); SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title, song.Length);
if (song.Length > 0)
songs.push_back (song); songs.push_back (song);
} }
MusicPlayer.playSongs(songs); MusicPlayer.playSongs(songs);
} }
else if (Params == "update_playlist")
{
if (MusicPlayer.isShuffleEnabled())
MusicPlayer.shuffleAndRebuildPlaylist();
MusicPlayer.rebuildPlaylist();
}
else if (Params == "previous") else if (Params == "previous")
MusicPlayer.previous(); MusicPlayer.previous();
else if (Params == "play") else if (Params == "play")

@ -55,14 +55,28 @@ public:
void update (); void update ();
bool isRepeatEnabled() const;
bool isShuffleEnabled() const;
// Build playlist UI from songs
void rebuildPlaylist();
// Randomize playlist and rebuild the ui
void shuffleAndRebuildPlaylist();
// Update playlist active row
void updatePlaylist(sint prevIndex = -1);
private: private:
// The playlist // The playlist
uint _CurrentSong; // If (!_Songs.empty()) must always be <_Songs.size() CSongs _CurrentSong;
uint _CurrentSongIndex; // If (!_Songs.empty()) must always be <_Songs.size()
std::vector<CSongs> _Songs; std::vector<CSongs> _Songs;
// State // State
enum TState { Stopped, Playing, Paused } _State; enum TState { Stopped, Playing, Paused } _State;
TTime _PlayStart;
TTime _PauseTime;
}; };
extern CMusicPlayer MusicPlayer; extern CMusicPlayer MusicPlayer;

Loading…
Cancel
Save