本节我们介绍下alexa的speaker管理:
引言:
从代码逻辑看speaker相关的
SetVolum、
AdjustVolum和SetMute是不考虑扬声器的类型(audioSpeaker ,speakSpeaker ,alertsSpeaker ),指令是不区分操作对象的,但是speaker有LOCAL,AVS_SYNCED之分,所有的指令只处理AVS_SYNCED类型的speaker,并把状态更新通知到AVS_SYNCED类型的被观察者对象,其实就是alert speaker不在处理范围之内,audiospeaker和speakSpeaker具体如何初始化音量相关操作还需要具体分析
:
1.初始化过程:
m_speakerManager = capabilityAgents::speakerManager::SpeakerManager::create(
{speakSpeaker, audioSpeaker, alertsSpeaker}, contextManager, m_connectionManager, exceptionSender);
SpeakerManager构造函数中,把speakSpeaker, audioSpeaker, alertsSpeaker存到map中:
for (auto speaker : speakers) {
m_speakerMap.insert(
std::pair<SpeakerInterface::Type, std::shared_ptr<SpeakerInterface>>(speaker->getSpeakerType(), speaker));
}
他们的原型是:
std::shared_ptr<alexaClientSDK::avsCommon::sdkInterfaces::SpeakerInterface> speakSpeaker =
std::static_pointer_cast<alexaClientSDK::avsCommon::sdkInterfaces::SpeakerInterface>(m_speakMediaPlayer);
std::shared_ptr<alexaClientSDK::avsCommon::sdkInterfaces::SpeakerInterface> audioSpeaker =
std::static_pointer_cast<alexaClientSDK::avsCommon::sdkInterfaces::SpeakerInterface>(m_audioMediaPlayer);
std::shared_ptr<alexaClientSDK::avsCommon::sdkInterfaces::SpeakerInterface> alertsSpeaker =
std::static_pointer_cast<alexaClientSDK::avsCommon::sdkInterfaces::SpeakerInterface>(m_alertsMediaPlayer);
配置:
configuration[SET_VOLUME] = BlockingPolicy::NON_BLOCKING;
configuration[ADJUST_VOLUME] = BlockingPolicy::NON_BLOCKING;
configuration[SET_MUTE] = BlockingPolicy::NON_BLOCKING;
2. 添加到观察者:
m_directiveSequencer->addDirectiveHandler(m_speakerManager)
=》
DirectiveRouter::addDirectiveHandler()
3. 指令处理过程:
void DirectiveSequencer::receiveDirectiveLocked(std::unique_lock<std::mutex>& lock)
=》
handled = m_directiveRouter.handleDirectiveWithPolicyHandleImmediately(directive);
if (!handled) {
ACSDK_INFO(LX("receiveDirectiveLocked").d("test", "444"));
//因为speak设置的是noblock模式,所以走这个分支
handled =
m_directiveProcessor->onDirective
(directive);
}
=》
DirectiveRouter::preHandleDirective()
=》
m_handlingQueue.push_back(directive);
m_wakeProcessingLoop.notify_one();
=》激活m_wakeProcessingLoop.wait()
bool DirectiveProcessor::handleDirectiveLocked(std::unique_lock<std::mutex>& lock)
=》
m_directiveRouter->handleDirective(directive, &policy);
bool DirectiveRouter::handleDirective()
=》
auto handlerAndPolicy = getHandlerAndPolicyLocked(directive);
HandlerCallScope scope(lock, this, handlerAndPolicy.handler);
auto result = handlerAndPolicy.handler->handleDirective(directive->getMessageId());
=》
void SpeakerManager::handleDirectiveImmediately(std::shared_ptr<AVSDirective> directive) {
handleDirective(std::make_shared<DirectiveInfo>(directive, nullptr));
};
3.1 speakerManager指令处理逻辑:
void SpeakerManager::handleDirective(std::shared_ptr<CapabilityAgent::DirectiveInfo> info)
1)case:SET_MUTE:处理函数为executeSetMute & executeSetVolume
(1)bool SpeakerManager::executeSetMute()
=>bool MediaPlayer::setMute(bool mute)
=>void MediaPlayer::handleSetMute()
{
g_object_set(m_pipeline.volume, "mute", static_cast<gboolean>(mute), NULL);
}
(2) bool SpeakerManager::executeSetVolume ()
=>bool MediaPlayer::setVolume(int8_t volume)
=>void MediaPlayer::handleSetVolume()
{
g_object_set(m_pipeline.volume, "volume", gstVolume, NULL);
}
2)case:ADJUST_VOLUME 处理函数为executeSetMute & executeAdjustVolume(在原有的音量上上调、下调音量)
bool MediaPlayer::adjustVolume(int8_t delta)
=>void MediaPlayer::handleAdjustVolume(std::promise<bool>* promise, int8_t delta)
{
gdouble gstVolume;
g_object_get(m_pipeline.volume, "volume", &gstVolume, NULL);
gdouble gstDelta;
if (!toGstDeltaVolume->normalize(delta, &gstDelta)) {
ACSDK_ERROR(LX("adjustVolumeFailed").d("reason", "normalizeVolumeFailed"));
promise->set_value(false);
return;
}
gstVolume += gstDelta;
// If adjustment exceeds bounds, cap at max/min.
gstVolume = std::min(gstVolume, static_cast<gdouble>(GST_SET_VOLUME_MAX));
gstVolume = std::max(gstVolume, static_cast<gdouble>(GST_SET_VOLUME_MIN));
g_object_set(m_pipeline.volume, "volume", gstVolume, NULL);
}
3)case:SET_MUTE 处理函数为executeSetMute
4)状态更新通知到AVS_SYNCED类型的被观察者对象:
bool SpeakerManager::updateContextManager()
{
if (SetStateResult::SUCCESS !=
m_contextManager->setState(VOLUME_STATE, buffer.GetString(), StateRefreshPolicy::NEVER)) {
ACSDK_ERROR(LX("updateContextManagerFailed").d("reason", "contextManagerSetStateFailed"));
return false;
}
}
SetStateResult ContextManager::setState(
const NamespaceAndName& stateProviderName,
const std::string& jsonState,
const StateRefreshPolicy& refreshPolicy,
const unsigned int stateRequestToken)