EXT-7337 WIP Voice morph previewing
Separate Play and Stop callbacks, to allow single click previews in the effect list.meow-7.2.2
parent
32826f31eb
commit
1ebbe19691
|
|
@ -43,6 +43,7 @@ LLFloaterVoiceEffect::LLFloaterVoiceEffect(const LLSD& key)
|
|||
{
|
||||
mCommitCallbackRegistrar.add("VoiceEffect.Record", boost::bind(&LLFloaterVoiceEffect::onClickRecord, this));
|
||||
mCommitCallbackRegistrar.add("VoiceEffect.Play", boost::bind(&LLFloaterVoiceEffect::onClickPlay, this));
|
||||
mCommitCallbackRegistrar.add("VoiceEffect.Stop", boost::bind(&LLFloaterVoiceEffect::onClickStop, this));
|
||||
mCommitCallbackRegistrar.add("VoiceEffect.Add", boost::bind(&LLFloaterVoiceEffect::onClickAdd, this));
|
||||
mCommitCallbackRegistrar.add("VoiceEffect.Activate", boost::bind(&LLFloaterVoiceEffect::onClickActivate, this));
|
||||
}
|
||||
|
|
@ -68,6 +69,7 @@ BOOL LLFloaterVoiceEffect::postBuild()
|
|||
mVoiceEffectList = getChild<LLScrollListCtrl>("voice_effect_list");
|
||||
if (mVoiceEffectList)
|
||||
{
|
||||
mVoiceEffectList->setCommitCallback(boost::bind(&LLFloaterVoiceEffect::onClickPlay, this));
|
||||
mVoiceEffectList->setDoubleClickCallback(boost::bind(&LLFloaterVoiceEffect::onClickActivate, this));
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +82,8 @@ BOOL LLFloaterVoiceEffect::postBuild()
|
|||
effect_interface->enablePreviewBuffer(true);
|
||||
}
|
||||
|
||||
update();
|
||||
refreshEffectList();
|
||||
updateControls();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -95,7 +98,7 @@ void LLFloaterVoiceEffect::onClose(bool app_quitting)
|
|||
}
|
||||
}
|
||||
|
||||
void LLFloaterVoiceEffect::update()
|
||||
void LLFloaterVoiceEffect::refreshEffectList()
|
||||
{
|
||||
if (!mVoiceEffectList)
|
||||
{
|
||||
|
|
@ -194,23 +197,42 @@ void LLFloaterVoiceEffect::update()
|
|||
|
||||
mVoiceEffectList->setValue(effect_interface->getVoiceEffect());
|
||||
mVoiceEffectList->setEnabled(true);
|
||||
}
|
||||
|
||||
void LLFloaterVoiceEffect::updateControls()
|
||||
{
|
||||
bool recording = false;
|
||||
bool playing = false;
|
||||
|
||||
LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
|
||||
if (effect_interface)
|
||||
{
|
||||
recording = effect_interface->isPreviewRecording();
|
||||
playing = effect_interface->isPreviewPlaying();
|
||||
}
|
||||
|
||||
// Update button states
|
||||
// *TODO: Should separate this from rebuilding the effects list, to avoid rebuilding it unnecessarily
|
||||
bool recording = effect_interface->isPreviewRecording();
|
||||
getChild<LLButton>("record_btn")->setVisible(!recording);
|
||||
getChild<LLButton>("record_stop_btn")->setVisible(recording);
|
||||
|
||||
getChild<LLButton>("play_btn")->setEnabled(effect_interface->isPreviewReady());
|
||||
bool playing = effect_interface->isPreviewPlaying();
|
||||
getChild<LLButton>("play_btn")->setVisible(!playing);
|
||||
getChild<LLButton>("play_stop_btn")->setVisible(playing);
|
||||
|
||||
getChild<LLButton>("play_btn")->setEnabled(effect_interface->isPreviewReady());
|
||||
|
||||
if (!mVoiceEffectList)
|
||||
{
|
||||
mVoiceEffectList->setValue(effect_interface->getVoiceEffect());
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLFloaterVoiceEffect::onVoiceEffectChanged(bool new_effects)
|
||||
{
|
||||
update();
|
||||
if (new_effects)
|
||||
{
|
||||
refreshEffectList();
|
||||
}
|
||||
updateControls();
|
||||
}
|
||||
|
||||
void LLFloaterVoiceEffect::onClickRecord()
|
||||
|
|
@ -219,11 +241,9 @@ void LLFloaterVoiceEffect::onClickRecord()
|
|||
LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
|
||||
if (effect_interface)
|
||||
{
|
||||
bool record = !effect_interface->isPreviewRecording();
|
||||
effect_interface->recordPreviewBuffer(record);
|
||||
getChild<LLButton>("record_btn")->setVisible(!record);
|
||||
getChild<LLButton>("record_stop_btn")->setVisible(record);
|
||||
effect_interface->recordPreviewBuffer();
|
||||
}
|
||||
updateControls();
|
||||
}
|
||||
|
||||
void LLFloaterVoiceEffect::onClickPlay()
|
||||
|
|
@ -239,11 +259,20 @@ void LLFloaterVoiceEffect::onClickPlay()
|
|||
LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
|
||||
if (effect_interface)
|
||||
{
|
||||
bool play = !effect_interface->isPreviewPlaying();
|
||||
effect_interface->playPreviewBuffer(play, effect_id);
|
||||
getChild<LLButton>("play_btn")->setVisible(!play);
|
||||
getChild<LLButton>("play_stop_btn")->setVisible(play);
|
||||
effect_interface->playPreviewBuffer(effect_id);
|
||||
}
|
||||
updateControls();
|
||||
}
|
||||
|
||||
void LLFloaterVoiceEffect::onClickStop()
|
||||
{
|
||||
LL_DEBUGS("Voice") << "Stop clicked" << LL_ENDL;
|
||||
LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
|
||||
if (effect_interface)
|
||||
{
|
||||
effect_interface->stopPreviewBuffer();
|
||||
}
|
||||
updateControls();
|
||||
}
|
||||
|
||||
void LLFloaterVoiceEffect::onClickAdd()
|
||||
|
|
|
|||
|
|
@ -53,13 +53,15 @@ public:
|
|||
virtual void onClose(bool app_quitting);
|
||||
|
||||
private:
|
||||
void update();
|
||||
void refreshEffectList();
|
||||
void updateControls();
|
||||
|
||||
/// Called by voice effect provider when voice effect list is changed.
|
||||
virtual void onVoiceEffectChanged(bool new_effects);
|
||||
|
||||
void onClickRecord();
|
||||
void onClickPlay();
|
||||
void onClickStop();
|
||||
void onClickAdd();
|
||||
void onClickActivate();
|
||||
|
||||
|
|
|
|||
|
|
@ -307,8 +307,9 @@ public:
|
|||
/// @name Preview buffer
|
||||
//@{
|
||||
virtual void enablePreviewBuffer(bool enable) = 0;
|
||||
virtual void recordPreviewBuffer(bool record) = 0;
|
||||
virtual void playPreviewBuffer(bool play, const LLUUID& effect_id = LLUUID::null) = 0;
|
||||
virtual void recordPreviewBuffer() = 0;
|
||||
virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null) = 0;
|
||||
virtual void stopPreviewBuffer() = 0;
|
||||
|
||||
virtual bool isPreviewRecording() = 0;
|
||||
virtual bool isPreviewReady() = 0;
|
||||
|
|
|
|||
|
|
@ -348,7 +348,8 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
|
|||
mCaptureBufferMode(false),
|
||||
mCaptureBufferRecording(false),
|
||||
mCaptureBufferRecorded(false),
|
||||
mCaptureBufferPlaying(false)
|
||||
mCaptureBufferPlaying(false),
|
||||
mPlayRequestCount(0)
|
||||
{
|
||||
mSpeakerVolume = scale_speaker_volume(0);
|
||||
|
||||
|
|
@ -1137,28 +1138,39 @@ void LLVivoxVoiceClient::stateMachine()
|
|||
case stateCaptureBufferPaused:
|
||||
if (!mCaptureBufferMode)
|
||||
{
|
||||
// Leaving capture mode.
|
||||
|
||||
mCaptureBufferRecording = false;
|
||||
mCaptureBufferRecorded = false;
|
||||
mCaptureBufferPlaying = false;
|
||||
|
||||
// Return to stateNoChannel to trigger reconnection to a channel.
|
||||
setState(stateNoChannel);
|
||||
}
|
||||
else if (mCaptureBufferRecording)
|
||||
{
|
||||
setState(stateCaptureBufferRecStart);
|
||||
// Update UI, should really be separated from the VoiceFont callback
|
||||
notifyVoiceFontObservers();
|
||||
}
|
||||
else if (mCaptureBufferPlaying)
|
||||
{
|
||||
setState(stateCaptureBufferPlayStart);
|
||||
notifyVoiceFontObservers();
|
||||
}
|
||||
break;
|
||||
|
||||
//MARK: stateCaptureBufferRecStart
|
||||
case stateCaptureBufferRecStart:
|
||||
captureBufferRecordStartSendMessage();
|
||||
|
||||
// Flag that something is recorded to allow playback.
|
||||
mCaptureBufferRecorded = true;
|
||||
|
||||
// Start the timer, recording will be stopped when it expires.
|
||||
mCaptureTimer.start();
|
||||
mCaptureTimer.setTimerExpirySec(CAPTURE_BUFFER_MAX_TIME);
|
||||
|
||||
// Update UI, should really use a separate callback.
|
||||
notifyVoiceFontObservers(false);
|
||||
|
||||
setState(stateCaptureBufferRecording);
|
||||
break;
|
||||
|
||||
|
|
@ -1167,27 +1179,47 @@ void LLVivoxVoiceClient::stateMachine()
|
|||
if (!mCaptureBufferMode || !mCaptureBufferRecording ||
|
||||
mCaptureBufferPlaying || mCaptureTimer.hasExpired())
|
||||
{
|
||||
mCaptureBufferRecording = false;
|
||||
// Stop recording
|
||||
captureBufferRecordStopSendMessage();
|
||||
mCaptureBufferRecording = false;
|
||||
|
||||
// Update UI, should really use a separate callback.
|
||||
notifyVoiceFontObservers(false);
|
||||
|
||||
setState(stateCaptureBufferPaused);
|
||||
notifyVoiceFontObservers();
|
||||
}
|
||||
break;
|
||||
|
||||
//MARK: stateCaptureBufferPlayStart
|
||||
case stateCaptureBufferPlayStart:
|
||||
captureBufferPlayStartSendMessage(mPreviewVoiceFontID);
|
||||
captureBufferPlayStartSendMessage(mPreviewVoiceFont);
|
||||
|
||||
// Store the voice font being previewed, so that we know to restart if it changes.
|
||||
mPreviewVoiceFontLast = mPreviewVoiceFont;
|
||||
|
||||
// Update UI, should really use a separate callback.
|
||||
notifyVoiceFontObservers(false);
|
||||
|
||||
setState(stateCaptureBufferPlaying);
|
||||
break;
|
||||
|
||||
//MARK: stateCaptureBufferPlaying
|
||||
case stateCaptureBufferPlaying:
|
||||
if (!mCaptureBufferMode || !mCaptureBufferPlaying || mCaptureBufferRecording)
|
||||
if (mCaptureBufferPlaying && mPreviewVoiceFont != mPreviewVoiceFontLast)
|
||||
{
|
||||
mCaptureBufferPlaying = false;
|
||||
// If the preview voice font changes, restart playing with the new font.
|
||||
setState(stateCaptureBufferPlayStart);
|
||||
}
|
||||
else if (!mCaptureBufferMode || !mCaptureBufferPlaying || mCaptureBufferRecording)
|
||||
{
|
||||
// Stop playing.
|
||||
captureBufferPlayStopSendMessage();
|
||||
mCaptureBufferPlaying = false;
|
||||
|
||||
// Update UI, should really use a separate callback.
|
||||
notifyVoiceFontObservers(false);
|
||||
|
||||
setState(stateCaptureBufferPaused);
|
||||
notifyVoiceFontObservers();
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1723,7 +1755,7 @@ void LLVivoxVoiceClient::stateMachine()
|
|||
{
|
||||
mAudioSessionChanged = false;
|
||||
notifyParticipantObservers();
|
||||
notifyVoiceFontObservers();
|
||||
notifyVoiceFontObservers(false);
|
||||
}
|
||||
else if (mAudioSession && mAudioSession->mParticipantsChanged)
|
||||
{
|
||||
|
|
@ -3546,7 +3578,11 @@ void LLVivoxVoiceClient::mediaCompletionEvent(std::string &sessionGroupHandle, s
|
|||
}
|
||||
else if (mediaCompletionType == "AuxBufferAudioRender")
|
||||
{
|
||||
mCaptureBufferPlaying = false;
|
||||
// Ignore all but the last stop event
|
||||
if (--mPlayRequestCount <= 0)
|
||||
{
|
||||
mCaptureBufferPlaying = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -6392,7 +6428,7 @@ bool LLVivoxVoiceClient::setVoiceEffect(const LLUUID& id)
|
|||
gSavedPerAccountSettings.setString("VoiceEffectDefault", id.asString());
|
||||
|
||||
sessionSetVoiceFontSendMessage(mAudioSession);
|
||||
notifyVoiceFontObservers();
|
||||
notifyVoiceFontObservers(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -6669,14 +6705,13 @@ void LLVivoxVoiceClient::accountGetSessionFontsResponse(int statusCode, const st
|
|||
}
|
||||
mVoiceFontsReceived = true;
|
||||
|
||||
notifyVoiceFontObservers(mVoiceFontsNew);
|
||||
mVoiceFontsNew = false;
|
||||
notifyVoiceFontObservers(true);
|
||||
}
|
||||
|
||||
void LLVivoxVoiceClient::accountGetTemplateFontsResponse(int statusCode, const std::string &statusString)
|
||||
{
|
||||
// Voice font list entries were updated via addVoiceFont() during parsing.
|
||||
notifyVoiceFontObservers();
|
||||
notifyVoiceFontObservers(true);
|
||||
}
|
||||
void LLVivoxVoiceClient::addObserver(LLVoiceEffectObserver* observer)
|
||||
{
|
||||
|
|
@ -6711,49 +6746,58 @@ void LLVivoxVoiceClient::enablePreviewBuffer(bool enable)
|
|||
}
|
||||
}
|
||||
|
||||
void LLVivoxVoiceClient::recordPreviewBuffer(bool record)
|
||||
void LLVivoxVoiceClient::recordPreviewBuffer()
|
||||
{
|
||||
if (record && !mCaptureBufferMode)
|
||||
if (!mCaptureBufferMode)
|
||||
{
|
||||
LL_DEBUGS("Voice") << "Cannot start recording, not in preview mode." << LL_ENDL;
|
||||
LL_DEBUGS("Voice") << "Not in voice effect preview mode, cannot start recording." << LL_ENDL;
|
||||
mCaptureBufferRecording = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mCaptureBufferRecording = record;
|
||||
mCaptureBufferRecording = true;
|
||||
}
|
||||
|
||||
void LLVivoxVoiceClient::playPreviewBuffer(bool play, const LLUUID& effect_id)
|
||||
void LLVivoxVoiceClient::playPreviewBuffer(const LLUUID& effect_id)
|
||||
{
|
||||
if (play)
|
||||
if (!mCaptureBufferMode)
|
||||
{
|
||||
if (mCaptureBufferMode && mCaptureBufferRecorded)
|
||||
{
|
||||
mPreviewVoiceFontID = effect_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Voice") << "No preview buffer to play." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
LL_DEBUGS("Voice") << "Not in voice effect preview mode, no buffer to play." << LL_ENDL;
|
||||
mCaptureBufferRecording = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mCaptureBufferPlaying = play;
|
||||
if (!mCaptureBufferRecorded)
|
||||
{
|
||||
// Can't play until we have something recorded!
|
||||
mCaptureBufferPlaying = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mPreviewVoiceFont = effect_id;
|
||||
mCaptureBufferPlaying = true;
|
||||
}
|
||||
|
||||
void LLVivoxVoiceClient::stopPreviewBuffer()
|
||||
{
|
||||
mCaptureBufferRecording = false;
|
||||
mCaptureBufferPlaying = false;
|
||||
}
|
||||
|
||||
bool LLVivoxVoiceClient::isPreviewRecording()
|
||||
{
|
||||
return mCaptureBufferRecording;
|
||||
return (mCaptureBufferMode && mCaptureBufferRecording);
|
||||
}
|
||||
|
||||
bool LLVivoxVoiceClient::isPreviewReady()
|
||||
{
|
||||
return mCaptureBufferRecorded;
|
||||
return (mCaptureBufferMode && mCaptureBufferRecorded);
|
||||
|
||||
}
|
||||
|
||||
bool LLVivoxVoiceClient::isPreviewPlaying()
|
||||
{
|
||||
return mCaptureBufferPlaying;
|
||||
return (mCaptureBufferMode && mCaptureBufferPlaying);
|
||||
}
|
||||
|
||||
void LLVivoxVoiceClient::captureBufferRecordStartSendMessage()
|
||||
|
|
@ -6811,6 +6855,10 @@ void LLVivoxVoiceClient::captureBufferPlayStartSendMessage(const LLUUID& voice_f
|
|||
{
|
||||
if(!mAccountHandle.empty())
|
||||
{
|
||||
// Track how may play requests are sent, so we know how many stop events to
|
||||
// expect before play actually stops.
|
||||
++mPlayRequestCount;
|
||||
|
||||
std::ostringstream stream;
|
||||
|
||||
LL_DEBUGS("Voice") << "Starting audio buffer playback." << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -258,8 +258,9 @@ public:
|
|||
/// @name Effect preview buffer
|
||||
//@{
|
||||
virtual void enablePreviewBuffer(bool enable);
|
||||
virtual void recordPreviewBuffer(bool record);
|
||||
virtual void playPreviewBuffer(bool play, const LLUUID& effect_id = LLUUID::null);
|
||||
virtual void recordPreviewBuffer();
|
||||
virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null);
|
||||
virtual void stopPreviewBuffer();
|
||||
|
||||
virtual bool isPreviewRecording();
|
||||
virtual bool isPreviewReady();
|
||||
|
|
@ -925,7 +926,9 @@ private:
|
|||
bool mCaptureBufferPlaying; // A voice sample is being played.
|
||||
|
||||
LLTimer mCaptureTimer;
|
||||
LLUUID mPreviewVoiceFontID;
|
||||
LLUUID mPreviewVoiceFont;
|
||||
LLUUID mPreviewVoiceFontLast;
|
||||
S32 mPlayRequestCount;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@
|
|||
top_delta="0"
|
||||
width="135">
|
||||
<button.commit_callback
|
||||
function="VoiceEffect.Record" />
|
||||
function="VoiceEffect.Stop" />
|
||||
</button>
|
||||
<button
|
||||
follows="left|bottom"
|
||||
|
|
@ -177,6 +177,6 @@
|
|||
top_delta="0"
|
||||
width="135">
|
||||
<button.commit_callback
|
||||
function="VoiceEffect.Play" />
|
||||
function="VoiceEffect.Stop" />
|
||||
</button>
|
||||
</floater>
|
||||
|
|
|
|||
Loading…
Reference in New Issue