概述
注:详情可关注微信公众号Deverloper_Taoists
概述
Alexa语音服务允许开发者通过麦克风和扬声器为连接的产品提供语音功能.一旦集成,你的产品将有权访问Alexa内置功能(如音乐播放、定时器和闹钟、快递追踪、电影列表、日历管理等)以及使用Alexa技能工具包开发的第三方技能
AVSDevice SDK 提供基于C ++(11或更高版本)的库,利用 AVS API 为 Alexa 启用的产品创建设备软件。它是模块化和抽象的,提供用于处理离散功能(如语音捕获,音频处理和通信)的组件,每个组件都会显示可以使用和定制的API,用于集成。它还包括一个示例应用程序,演示与AVS的互动
这一节,主要分析从AlexaServer接收到数据后到对应能力集代理去处理(以SpeechSynthesizer为例) 这一个过程
主要流程分析
依然以SampleAPP 为例。前文说到在HTTP2Stream 中的initPost()中设置了curl 相关的readcallback 函数
类似的HTTP2Stream的initGet-> setCommonOptions-> setWriteCallback设置了Http线程从服务器接收数据后的回调函数为writeCallback函数。先分析http2stream->messagerouter大致流程如下图
Step 1. HTTP2Stream::writeCallback()
首先Http线程收到数据后回调HTTP2Stream::writeCallback()
返回200 后开始解析数据(MIME多用途互联网邮件扩展类型,姑且认为是一种包含多种数据格式的标准吧)
HTTP2Stream,包含MimeParser对象,看它的feed()方法
Step 2. MimeParser::feed()
MimeParser对象里包含一个类型为MultipartReader的对象,看它的feed函数,最终调到MultipartParser对象的feed函数,主要是对数据进行解析,比如获取指令名称,将playload数据写入SDS中等等,下面看关键部分
看下callback(onPartBegin);最终回调到MimeParser::partBeginCallback(),
主要是创建一个attachementwriter对象,用于后面写入数据。在回到上一步看下processpartData(),同理最终回调到MimeParser::partDataCallback函数,
看到了么writeDataToAttachment将数据写入SDS中去了…
解析完了后会调用partEndCallback函数
看下parser->m_messageConsumer->consumeMessage(),继续跟,来到了MessageRouter::consumeMessage()
在看一下面的流程图
Step 3. notifyObserverOnReceive()
比较简单,首先获取对应的观察者,让后调用观察者的receive 对象,那么观察者从哪来,回到DefaultClient::initialize()会创建一个AVSConnectionManager 对象(acl::AVSConnectionManager::create),继续看它的create函数
显然这个观察者是AVSConnectionManager对象。
又有了,慢慢看发现这个observers在DefaultClient::initialize()中设置为MessageInterpreter对象
先是一大堆判断,然后终于进入到正题。
Step 4. DirectiveSequencer::onDirective()
很简单,就是入队列,然后唤醒receivingLoop中的休眠,然后调用receiveDirectiveLocked
首先从指令队列里取队列,然后再看一下
解析指令对应的执行策略(就这么说吧),举个例子
看到了吧,是BLOCKING,直接返回false。返回到receiveDirectiveLocked,走如下分支,m_directiveProcessor->onDirective(),
判断指令的DialogRequestId是否等于当前会话的ID,若是再走下一步(这里延时或者打断会导致两者不相等),接着调用内部对象DirectiveRouter的preHandleDirective 函数,
好了,让了一圈,来到了代理SpeechSynthesizer中
没什么好说的,executePreHandleAfterValidation,主要是做一些判断。
DirectiveProcessor::onDirective()函数看接下来的流程。很简单,入队列,唤醒
主要看
类似的在调用内部对象DirectiveRouter的handleDirective方法,同样的,最终来到SpeechSynthesizer中
看下addToDirectiveQueue()先是入队列,然后调用forcusManager 的acquireChannel函数,然后acquireChannel->acquireChannelHelper->setChannelFocus->onFocusChanged,又回到了SpeechSynthesizer的
OnForcusChanged(),
先看executeStateChange()将m_desiredState 赋值给newState,看case语句,调用startPlaying()
最终来到了MediaPlayer先设置url,然后开始play->handlePlay,handlePlay 使用gst_element_set_state(m_pipeline.pipeline,startingState);设置gstream的状态为GST_STATE_PLAYING,
在看下
MediaPlayer::handleBusMessage()
很多,看重点,当有数据可用时再调用sendPlaybackStarted()
通知观察者,观察者为SpeechSynthesizer对象,进入该对象
重点看
接着
setCurrentStateLocked()函数首先调用executeProvideState,来更行状态,接着调用observer 对象的onStateChanged()方法,通知会话状态管理者DialogUXStateAggregator。
好了,贴了很多代码,先这样…
最后
以上就是土豪柜子为你收集整理的Alexa Sdk学习笔记三的全部内容,希望文章能够帮你解决Alexa Sdk学习笔记三所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复