lib/punchblock/component/output.rb in punchblock-1.9.4 vs lib/punchblock/component/output.rb in punchblock-2.0.0.beta1

- old
+ new

@@ -3,178 +3,134 @@ module Punchblock module Component class Output < ComponentNode register :output, :output - ## - # Creates an Rayo Output command - # - # @param [Hash] options - # @option options [String, Optional] :text to speak back - # @option options [String, Optional] :voice with which to render TTS - # @option options [String, Optional] :ssml document to render TTS - # @option options [Symbol] :interrupt_on input type on which to interrupt output. May be :speech, :dtmf or :any - # @option options [Integer] :start_offset Indicates some offset through which the output should be skipped before rendering begins. - # @option options [true, false] :start_paused Indicates wether or not the component should be started in a paused state to be resumed at a later time. - # @option options [Integer] :repeat_interval Indicates the duration of silence that should space repeats of the rendered document. - # @option options [Integer] :repeat_times Indicates the number of times the output should be played. - # @option options [Integer] :max_time Indicates the maximum amount of time for which the output should be allowed to run before being terminated. Includes repeats. - # - # @return [Command::Output] an Rayo "output" command - # - # @example - # output :text => 'Hello brown cow.' - # - # returns: - # <output xmlns="urn:xmpp:rayo:output:1">Hello brown cow.</output> - # - def self.new(options = {}) - super().tap do |new_node| - case options - when Hash - new_node.ssml = options.delete(:ssml) if options[:ssml] - new_node << options.delete(:text) if options[:text] - options.each_pair { |k,v| new_node.send :"#{k}=", v } - when Nokogiri::XML::Element - new_node.inherit options + class Document < RayoNode + register :document, :output + + SSML_CONTENT_TYPE = 'application/ssml+xml' + + # @return [String] the URL from which the fetch the grammar + attribute :url + + # @return [String] the document content type + attribute :content_type, String, default: ->(grammar, attribute) { grammar.url ? nil : SSML_CONTENT_TYPE } + + # @return [String, RubySpeech::SSML::Speak, URIList] the document + attribute :value + + def inherit(xml_node) + super + self.value = if ssml? + RubySpeech::SSML.import xml_node.content + elsif urilist? + URIList.import xml_node.content + else + xml_node.content end + self end - end - ## - # @return [String] the TTS voice to use - # - def voice - read_attr :voice - end + def rayo_attributes + { + 'url' => url, + 'content-type' => content_type + } + end - ## - # @param [String] voice to use when rendering TTS - # - def voice=(voice) - write_attr :voice, voice - end + def rayo_children(root) + root.cdata xml_value + super + end - ## - # @return [String] the SSML document to render TTS - # - def ssml - node = children.first - RubySpeech::SSML.import node if node - end + private - ## - # @param [String] ssml the SSML document to render TTS - # - def ssml=(ssml) - return unless ssml - unless ssml.is_a?(RubySpeech::SSML::Element) - ssml = RubySpeech::SSML.import ssml + def xml_value + if ssml? + value.to_xml + elsif urilist? + value.to_s + elsif + value + end end - self << ssml - end - ## - # @return [Symbol] input type on which to interrupt output - # - def interrupt_on - read_attr :'interrupt-on', :to_sym - end + def ssml? + content_type == SSML_CONTENT_TYPE + end - ## - # @param [Symbol] other input type on which to interrupt output. May be :speech, :dtmf or :any - # - def interrupt_on=(other) - write_attr :'interrupt-on', other + def urilist? + content_type == 'text/uri-list' + end end - ## - # @return [Integer] Indicates some offset through which the output should be skipped before rendering begins. - # - def start_offset - read_attr :'start-offset', :to_i + def inherit(xml_node) + document_nodes = xml_node.xpath 'ns:document', ns: self.class.registered_ns + self.render_documents = document_nodes.to_a.map { |node| Document.from_xml node } + super end - ## - # @param [Integer] other Indicates some offset through which the output should be skipped before rendering begins. - # - def start_offset=(other) - write_attr :'start-offset', other, :to_i - end + # @return [String] the TTS voice to use + attribute :voice, String - ## - # @return [true, false] Indicates wether or not the component should be started in a paused state to be resumed at a later time. - # - def start_paused - read_attr(:'start-paused') == 'true' - end + # @return [Symbol] input type on which to interrupt output + attribute :interrupt_on, Symbol - ## - # @param [true, false] other Indicates wether or not the component should be started in a paused state to be resumed at a later time. - # - def start_paused=(other) - write_attr :'start-paused', other, :to_s - end + # @return [Integer] Indicates some offset through which the output should be skipped before rendering begins. + attribute :start_offset, Integer - ## + # @return [true, false] Indicates wether or not the component should be started in a paused state to be resumed at a later time. + attribute :start_paused, Boolean, default: false + # @return [Integer] Indicates the duration of silence that should space repeats of the rendered document. - # - def repeat_interval - read_attr :'repeat-interval', :to_i - end + attribute :repeat_interval, Integer - ## - # @param [Integer] other Indicates the duration of silence that should space repeats of the rendered document. - # - def repeat_interval=(other) - write_attr :'repeat-interval', other, :to_i - end - - ## # @return [Integer] Indicates the number of times the output should be played. - # - def repeat_times - read_attr :'repeat-times', :to_i - end + attribute :repeat_times, Integer - ## - # @param [Integer] other Indicates the number of times the output should be played. - # - def repeat_times=(other) - write_attr :'repeat-times', other, :to_i - end - - ## # @return [Integer] Indicates the maximum amount of time for which the output should be allowed to run before being terminated. Includes repeats. - # - def max_time - read_attr :'max-time', :to_i - end + attribute :max_time, Integer - ## - # @param [Integer] other Indicates the maximum amount of time for which the output should be allowed to run before being terminated. Includes repeats. - # - def max_time=(other) - write_attr :'max-time', other, :to_i + # @return [String] the rendering engine requested by the component + attribute :renderer, String + + def rayo_attributes + { + 'voice' => voice, + 'interrupt-on' => interrupt_on, + 'start-offset' => start_offset, + 'start-paused' => start_paused, + 'repeat-interval' => repeat_interval, + 'repeat-times' => repeat_times, + 'max-time' => max_time, + 'renderer' => renderer + } end - ## - # @return [String] the rendering engine requested by the component - # - def renderer - read_attr :renderer + def rayo_children(root) + render_documents.each do |render_document| + render_document.to_rayo root.parent + end + super end + # @return [Document] the document to render + attribute :render_documents, Array[Document], default: [] + ## - # @param [String] the rendering engine to use with this component + # @param [Hash] other + # @option other [String] :content_type the document content type + # @option other [String] :value the output doucment + # @option other [String] :url the url from which to fetch the document # - def renderer=(renderer) - write_attr :renderer, renderer + def render_document=(other) + self.render_documents = [other].compact end - def inspect_attributes - super + [:voice, :ssml, :interrupt_on, :start_offset, :start_paused, :repeat_interval, :repeat_times, :max_time, :renderer] + def ssml=(other) + self.render_documents = [{:value => other}] end state_machine :state do event :paused do transition :executing => :paused @@ -279,34 +235,26 @@ end class Seek < CommandNode # :nodoc: register :seek, :output - def self.new(options = {}) - super.tap do |new_node| - new_node.direction = options[:direction] - new_node.amount = options[:amount] - end - end + attribute :direction + attribute :amount - def direction=(other) - write_attr :direction, other - end - - def amount=(other) - write_attr :amount, other - end - def request! source.seeking! super end def execute! source.stopped_seeking! super end + + def rayo_attributes + {'direction' => direction, 'amount' => amount} + end end ## # Creates an Rayo speed up message for the current Output # @@ -494,11 +442,15 @@ super end end class Complete - class Success < Event::Complete::Reason - register :success, :output_complete + class Finish < Event::Complete::Reason + register :finish, :output_complete + end + + class MaxTime < Event::Complete::Reason + register :'max-time', :output_complete end end end # Output end # Command end # Punchblock