Files
SingularityViewer/indra/newview/shfloatermediaticker.cpp
Shyotl 7fb05e6a48 Audio engine changes:
-Idle tick is now responsible for dispatching all pending sound sources, as such improves priority sorting.
-Added ui sound precache mechanisms (to fetch sounds without associated soundsources)
-Audio engine no logner available pre-login or upon disconnect, for simplicity.
-General cleanup to the audio engine/impl.
-Fixed some gAudiop calls that were lacking prerequisite null checks.
-Added 'isUpstreamOK' procuedure to LLAssetStorage to allow avoidance of making requests when there is no upstream host connection.
2013-10-12 02:49:11 -05:00

272 lines
7.6 KiB
C++

#include "llviewerprecompiledheaders.h"
#include "shfloatermediaticker.h"
// Library includes
#include "llaudioengine.h"
#include "lliconctrl.h"
#include "llstreamingaudio.h"
#include "lluictrlfactory.h"
// Viewer includes
#include "llviewercontrol.h"
SHFloaterMediaTicker::SHFloaterMediaTicker() : LLFloater()/*, LLSingleton<SHFloaterMediaTicker>()*/,
mPlayState(STATE_PLAYING),
mArtistScrollChars(0),
mTitleScrollChars(0),
mCurScrollChar(0),
mTickerBackground(NULL),
mArtistText(NULL),
mTitleText(NULL),
mVisualizer(NULL)
{
setIsChrome(TRUE);
if(gAudiop->getStreamingAudioImpl()->supportsWaveData())
LLUICtrlFactory::getInstance()->buildFloater(this, "sh_floater_media_ticker_visualizer.xml");
else
LLUICtrlFactory::getInstance()->buildFloater(this, "sh_floater_media_ticker.xml");
}
/*virtual*/ BOOL SHFloaterMediaTicker::postBuild()
{
mTickerBackground = getChild<LLIconCtrl>("ticker_background");
mArtistText = getChild<LLTextBox>("artist_text",true,false);
mTitleText = getChild<LLTextBox>("title_text",true,false);
mVisualizer = getChild<LLUICtrl>("visualizer_box",true,false);
mszLoading = getString("loading");
mszPaused = getString("paused");
mOscillatorColor = gColors.getColor("SHMediaTickerOscillatorColor");
setPaused(true);
return LLFloater::postBuild();
}
/*virtual*/ void SHFloaterMediaTicker::draw()
{
updateTickerText();
LLFloater::draw();
drawOscilloscope();
}
/*virtual*/ void SHFloaterMediaTicker::onOpen()
{
LLFloater::onOpen();
gSavedSettings.setBOOL("SHShowMediaTicker", TRUE);
}
/*virtual*/ void SHFloaterMediaTicker::onClose(bool app_quitting)
{
LLFloater::onClose(app_quitting);
if (!app_quitting)
{
gSavedSettings.setBOOL("SHShowMediaTicker", FALSE);
}
}
/*virtual*/void SHFloaterMediaTicker::reshape(S32 width, S32 height, BOOL called_from_parent/*=TRUE*/)
{
//disable height change.
bool width_changed = (getRect().getWidth() != width);
LLFloater::reshape(width,getRect().getHeight(), called_from_parent);
if(width_changed)
{
if(mTitleText)
mTitleScrollChars = countExtraChars(mTitleText,mszTitle);
if(mArtistText)
mArtistScrollChars = countExtraChars(mArtistText,mszArtist);
resetTicker();
}
}
void SHFloaterMediaTicker::updateTickerText() //called via draw.
{
if(!gAudiop)
return;
bool stream_paused = gAudiop->getStreamingAudioImpl()->isPlaying() != 1; //will return 1 if playing.
bool dirty = setPaused(stream_paused);
if(!stream_paused)
{
if(dirty || mUpdateTimer.getElapsedTimeF64() >= .5f)
{
mUpdateTimer.reset();
const LLSD* metadata = gAudiop->getStreamingAudioImpl()->getMetaData();
LLSD artist = metadata ? metadata->get("ARTIST") : LLSD();
LLSD title = metadata ? metadata->get("TITLE") : LLSD();
dirty |= setArtist(artist.isDefined() ? artist.asString() : mszLoading);
dirty |= setTitle(title.isDefined() ? title.asString() : mszLoading);
if(artist.isDefined() && title.isDefined())
mLoadTimer.stop();
else if(dirty)
mLoadTimer.start();
else if(mLoadTimer.getStarted() && mLoadTimer.getElapsedTimeF64() > 10.f) //It has been 10 seconds.. give up.
{
if(!artist.isDefined())
dirty |= setArtist("");
if(!title.isDefined())
dirty |= setTitle("");
mLoadTimer.stop();
}
}
}
if(dirty)
resetTicker();
else
iterateTickerOffset();
}
void SHFloaterMediaTicker::drawOscilloscope() //called via draw.
{
if(!gAudiop || !mVisualizer || !gAudiop->getStreamingAudioImpl()->supportsWaveData())
return;
static const S32 NUM_LINE_STRIPS = 64; //How many lines to draw. 64 is more than enough.
static const S32 WAVE_DATA_STEP_SIZE = 4; //Increase to provide more history at expense of cpu/memory.
static const S32 NUM_WAVE_DATA_VALUES = NUM_LINE_STRIPS*WAVE_DATA_STEP_SIZE; //Actual buffer size. Don't toy with this. Change above vars to tweak.
static F32 buf[NUM_WAVE_DATA_VALUES];
LLRect root_rect = mVisualizer->getRect();
F32 height = root_rect.getHeight();
F32 height_scale = height / 2.f; //WaveData ranges from 1 to -1, so height_scale = height / 2
F32 width = root_rect.getWidth();
F32 width_scale = width / (F32)NUM_WAVE_DATA_VALUES;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4fv(mOscillatorColor.mV);
gGL.pushMatrix();
gGL.translatef((F32)root_rect.mLeft, (F32)root_rect.mBottom + height*.5f, 0.f);
gGL.begin( LLRender::LINE_STRIP );
if(mPlayState == STATE_PAUSED || !gAudiop->getStreamingAudioImpl()->getWaveData(&buf[0],NUM_WAVE_DATA_VALUES,WAVE_DATA_STEP_SIZE))
{
gGL.vertex2i(0,0);
gGL.vertex2i((S32)width,0);
}
else
for(S32 i = NUM_WAVE_DATA_VALUES-1; i>=0;i-=WAVE_DATA_STEP_SIZE)
gGL.vertex2f((F32)i * width_scale, buf[i]*height_scale);
gGL.end();
gGL.popMatrix();
gGL.flush();
}
bool SHFloaterMediaTicker::setPaused(bool pause)
{
if(pause == (mPlayState == STATE_PAUSED))
return false;
mPlayState = pause ? STATE_PAUSED : STATE_PLAYING;
if(pause)
{
setArtist(mszPaused);
setTitle(mszPaused);
}
return true;
}
void SHFloaterMediaTicker::resetTicker()
{
mScrollTimer.reset();
mCurScrollChar=0;
if(mArtistText) mArtistText->setText(LLStringExplicit(mszArtist.substr(0,mszArtist.length()-mArtistScrollChars)));
if(mTitleText) mTitleText->setText(LLStringExplicit(mszTitle.substr(0,mszTitle.length()-mTitleScrollChars)));
}
bool SHFloaterMediaTicker::setArtist(const std::string &artist)
{
if(!mArtistText || mszArtist == artist)
return false;
mszArtist = artist;
mArtistText->setText(mszArtist);
mArtistScrollChars = countExtraChars(mArtistText,mszArtist);
return true;
}
bool SHFloaterMediaTicker::setTitle(const std::string &title)
{
if(!mTitleText || mszTitle == title)
return false;
mszTitle=title;
mTitleText->setText(mszTitle);
mTitleScrollChars = countExtraChars(mTitleText,mszTitle);
return true;
}
S32 SHFloaterMediaTicker::countExtraChars(LLTextBox *texbox, const std::string &text)
{
S32 text_width = texbox->getTextPixelWidth();
S32 box_width = texbox->getRect().getWidth();
if(text_width > box_width)
{
const LLFontGL* font = texbox->getFont();
for(S32 count = 1;count<(S32)text.length();count++)
{
//This isn't very efficient...
const std::string substr = text.substr(0,text.length()-count);
if(font->getWidth(substr) <= box_width)
return count;
}
}
return 0;
}
void SHFloaterMediaTicker::iterateTickerOffset()
{
if( (mPlayState != STATE_PAUSED) &&
(mArtistScrollChars || mTitleScrollChars) &&
((!mCurScrollChar && mScrollTimer.getElapsedTimeF32() >= 5.f) ||
( mCurScrollChar && mScrollTimer.getElapsedTimeF32() >= .5f)))
{
if(++mCurScrollChar > llmax(mArtistScrollChars, mTitleScrollChars))
{
if(mScrollTimer.getElapsedTimeF32() >= 2.f) //pause for a bit when it reaches beyond last character.
resetTicker();
}
else
{
mScrollTimer.reset();
if(mArtistText && mCurScrollChar <= mArtistScrollChars)
{
mArtistText->setText(LLStringExplicit(mszArtist.substr(mCurScrollChar,mszArtist.length()-mArtistScrollChars+mCurScrollChar)));
}
if(mTitleText && mCurScrollChar <= mTitleScrollChars)
{
mTitleText->setText(LLStringExplicit(mszTitle.substr(mCurScrollChar,mszTitle.length()-mTitleScrollChars+mCurScrollChar)));
}
}
}
}
/*static*/
void SHFloaterMediaTicker::showInstance()
{
if(!handle_ticker_enabled(NULL))
return;
if(!SHFloaterMediaTicker::instanceExists())
{
SHFloaterMediaTicker::getInstance();
}
}
BOOL handle_ticker_enabled(void *)
{
return gAudiop && gAudiop->getStreamingAudioImpl() && gAudiop->getStreamingAudioImpl()->supportsMetaData();
}
void handle_ticker_toggle(void *)
{
if(!handle_ticker_enabled(NULL))
return;
if(!SHFloaterMediaTicker::instanceExists())
{
SHFloaterMediaTicker::getInstance();
}
else
{
SHFloaterMediaTicker::getInstance()->close();
}
}