#include "nw4r/snd/snd_RemoteSpeaker.h" #include "common.h" #include "nw4r/snd/snd_RemoteSpeakerManager.h" #include "nw4r/ut/ut_Lock.h" #include namespace nw4r { namespace snd { RemoteSpeaker::RemoteSpeaker() : mInitFlag(false), mPlayFlag(false), mEnableFlag(false), mFirstEncodeFlag(false), mValidCallbackFlag(false), mCommandBusyFlag(false), // mForceResumeFlag(false), mState(STATE_INVALID), mUserCommand(COMMAND_NONE), mInternalCommand(COMMAND_NONE), mWpadCallback(nullptr) { OSCreateAlarm(&mContinueAlarm); OSSetAlarmUserData(&mContinueAlarm, this); OSCreateAlarm(&mIntervalAlarm); OSSetAlarmUserData(&mIntervalAlarm, this); } void RemoteSpeaker::InitParam() { ClearParam(); // mForceResumeFlag = false; mContinueFlag = false; mPlayFlag = false; mEnableFlag = true; mIntervalFlag = false; } void RemoteSpeaker::ClearParam() { mPlayFlag = false; mEnableFlag = false; OSCancelAlarm(&mContinueAlarm); mContinueFlag = false; OSCancelAlarm(&mIntervalAlarm); mIntervalFlag = false; } bool RemoteSpeaker::Setup(WPADCallback pCallback) { ut::AutoInterruptLock lock; InitParam(); if (mWpadCallback != NULL) { mWpadCallback(mChannelIndex, WPAD_ERR_OK); mValidCallbackFlag = false; } mUserCommand = COMMAND_SPEAKER_ON; mWpadCallback = pCallback; mInitFlag = true; return true; } void RemoteSpeaker::Shutdown(WPADCallback pCallback) { ut::AutoInterruptLock lock; ClearParam(); if (mWpadCallback != NULL) { mWpadCallback(mChannelIndex, WPAD_ERR_OK); mValidCallbackFlag = false; } mUserCommand = COMMAND_SPEAKER_OFF; mWpadCallback = pCallback; mInitFlag = false; } bool RemoteSpeaker::EnableOutput(bool enable) { if (!mInitFlag) { return false; } mEnableFlag = enable; return true; } bool RemoteSpeaker::IsEnabledOutput() const { if (!mInitFlag) { return false; } return mEnableFlag; } void RemoteSpeaker::Update() { if (mCommandBusyFlag) { return; } SpeakerCommand command = mUserCommand != COMMAND_NONE ? mUserCommand : mInternalCommand; mUserCommand = COMMAND_NONE; mInternalCommand = COMMAND_NONE; ExecCommand(command); } void RemoteSpeaker::ExecCommand(SpeakerCommand command) { switch (command) { case COMMAND_NONE: { break; } case COMMAND_SPEAKER_ON: { mValidCallbackFlag = true; mCommandBusyFlag = true; mState = STATE_EXEC_SPEAKER_ON; WPADControlSpeaker(mChannelIndex, WPAD_SPEAKER_ON, SpeakerOnCallback); break; } case COMMAND_SPEAKER_PLAY: { mValidCallbackFlag = true; mCommandBusyFlag = true; mState = STATE_EXEC_SPEAKER_PLAY; WPADControlSpeaker(mChannelIndex, WPAD_SPEAKER_PLAY, SpeakerPlayCallback); break; } case COMMAND_SPEAKER_OFF: { mValidCallbackFlag = true; mCommandBusyFlag = true; mState = STATE_EXEC_SPEAKER_OFF; WPADControlSpeaker(mChannelIndex, WPAD_SPEAKER_OFF, SpeakerOffCallback); break; } } } void RemoteSpeaker::UpdateStreamData(const s16* pRmtSamples) { if (!IsAvailable()) { return; } bool playFlag = true; bool silentFlag = mEnableFlag ? IsAllSampleZero(pRmtSamples) : true; if (silentFlag /*|| mForceResumeFlag*/) { playFlag = false; } bool firstFlag = !mPlayFlag && playFlag; bool lastFlag = mPlayFlag && !playFlag; if (playFlag) { ut::AutoInterruptLock lock; if (!WPADCanSendStreamData(mChannelIndex)) { return; } u32 wencMode = !mFirstEncodeFlag ? WENC_FLAG_USER_INFO : 0; mFirstEncodeFlag = false; u8 adpcmBuffer[SAMPLES_PER_ENCODED_PACKET]; WENCGetEncodeData(&mEncodeInfo, wencMode, pRmtSamples, SAMPLES_PER_AUDIO_PACKET, adpcmBuffer); s32 result = WPADSendStreamData(mChannelIndex, adpcmBuffer, SAMPLES_PER_ENCODED_PACKET); if (result != WPAD_ERR_OK) { mInternalCommand = COMMAND_SPEAKER_ON; mState = STATE_INVALID; InitParam(); return; } } if (firstFlag) { ut::AutoInterruptLock lock; if (!mContinueFlag) { OSSetAlarm(&mContinueAlarm, OS_SEC_TO_TICKS(CONTINUOUS_PLAY_INTERVAL_MINUTES * 60LL), ContinueAlarmHandler); mContinueBeginTime = OSGetTime(); mContinueFlag = true; } OSCancelAlarm(&mIntervalAlarm); mIntervalFlag = false; } if (lastFlag) { ut::AutoInterruptLock lock; mIntervalFlag = true; OSCancelAlarm(&mIntervalAlarm); OSSetAlarm(&mIntervalAlarm, OS_SEC_TO_TICKS(1LL), IntervalAlarmHandler); } mPlayFlag = playFlag; } bool RemoteSpeaker::IsAllSampleZero(const s16* pSample) { const u32* pBuffer = reinterpret_cast(pSample); bool zeroFlag = true; for (int i = 0; i < SAMPLES_PER_ENCODED_PACKET; i++) { if (pBuffer[i] != 0) { zeroFlag = false; break; } } return zeroFlag; } void RemoteSpeaker::SpeakerOnCallback(s32 chan, s32 result) { RemoteSpeaker& r = detail::RemoteSpeakerManager::GetInstance().GetRemoteSpeaker(chan); switch (result) { case WPAD_ERR_OK: { r.mFirstEncodeFlag = true; std::memset(&r.mEncodeInfo, 0, sizeof(WENCInfo)); r.mState = STATE_SPEAKER_ON; r.mInternalCommand = COMMAND_SPEAKER_PLAY; break; } case WPAD_ERR_BUSY: { r.mInternalCommand = COMMAND_SPEAKER_ON; break; } case WPAD_ERR_TRANSFER: { r.mState = STATE_INVALID; break; } case WPAD_ERR_NO_CONTROLLER: { r.mState = STATE_INVALID; break; } default: { r.mState = STATE_INVALID; break; } } if (result != WPAD_ERR_OK && result != WPAD_ERR_BUSY) { r.NotifyCallback(chan, result); } r.mCommandBusyFlag = false; } void RemoteSpeaker::SpeakerPlayCallback(s32 chan, s32 result) { RemoteSpeaker& r = detail::RemoteSpeakerManager::GetInstance().GetRemoteSpeaker(chan); switch (result) { case WPAD_ERR_OK: { r.mState = STATE_SPEAKER_PLAY; break; } case WPAD_ERR_BUSY: { r.mInternalCommand = COMMAND_SPEAKER_PLAY; break; } case WPAD_ERR_TRANSFER: { r.mState = STATE_INVALID; break; } case WPAD_ERR_NO_CONTROLLER: { r.mState = STATE_INVALID; break; } default: { r.mState = STATE_INVALID; break; } } if (result != WPAD_ERR_BUSY) { r.NotifyCallback(chan, result); } r.mCommandBusyFlag = false; } void RemoteSpeaker::SpeakerOffCallback(s32 chan, s32 result) { RemoteSpeaker& r = detail::RemoteSpeakerManager::GetInstance().GetRemoteSpeaker(chan); switch (result) { case WPAD_ERR_OK: { r.mState = STATE_SPEAKER_OFF; break; } case WPAD_ERR_BUSY: { r.mInternalCommand = COMMAND_SPEAKER_OFF; break; } case WPAD_ERR_TRANSFER: { r.mState = STATE_INVALID; break; } case WPAD_ERR_NO_CONTROLLER: { r.mState = STATE_INVALID; break; } default: { r.mState = STATE_INVALID; break; } } if (result != WPAD_ERR_BUSY) { r.NotifyCallback(chan, result); } r.mCommandBusyFlag = false; } void RemoteSpeaker::NotifyCallback(s32 chan, s32 result) { if (mValidCallbackFlag && mWpadCallback != NULL) { mWpadCallback(chan, result); mWpadCallback = NULL; } } void RemoteSpeaker::ContinueAlarmHandler(OSAlarm* pAlarm, OSContext* pCtx) { #pragma unused(pCtx) ut::AutoInterruptLock lock; RemoteSpeaker* p = static_cast(OSGetAlarmUserData(pAlarm)); // p->mForceResumeFlag = true; // p->mContinueFlag = false; } void RemoteSpeaker::IntervalAlarmHandler(OSAlarm* pAlarm, OSContext* pCtx) { #pragma unused(pCtx) ut::AutoInterruptLock lock; RemoteSpeaker* p = static_cast(OSGetAlarmUserData(pAlarm)); if (p->mIntervalFlag) { OSCancelAlarm(&p->mContinueAlarm); // p->mForceResumeFlag = false; p->mContinueFlag = false; } p->mIntervalFlag = false; } } // namespace snd } // namespace nw4r