punchblock 1.9.4 → 2.0.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -2
- data/CHANGELOG.md +17 -0
- data/Gemfile +1 -0
- data/Guardfile +4 -0
- data/README.markdown +6 -0
- data/Rakefile +16 -0
- data/benchmarks/ami_event_name_comparison.rb +14 -0
- data/benchmarks/channel.rb +27 -0
- data/lib/punchblock/client.rb +2 -6
- data/lib/punchblock/command/accept.rb +3 -24
- data/lib/punchblock/command/answer.rb +3 -24
- data/lib/punchblock/command/dial.rb +24 -76
- data/lib/punchblock/command/hangup.rb +3 -19
- data/lib/punchblock/command/join.rb +21 -70
- data/lib/punchblock/command/mute.rb +3 -3
- data/lib/punchblock/command/redirect.rb +6 -39
- data/lib/punchblock/command/reject.rb +14 -54
- data/lib/punchblock/command/unjoin.rb +8 -40
- data/lib/punchblock/command/unmute.rb +3 -3
- data/lib/punchblock/command_node.rb +0 -17
- data/lib/punchblock/component/asterisk/agi/command.rb +20 -127
- data/lib/punchblock/component/asterisk/ami/action.rb +30 -117
- data/lib/punchblock/component/component_node.rb +1 -1
- data/lib/punchblock/component/input.rb +89 -268
- data/lib/punchblock/component/output.rb +106 -154
- data/lib/punchblock/component/prompt.rb +51 -0
- data/lib/punchblock/component/record.rb +41 -130
- data/lib/punchblock/component.rb +1 -0
- data/lib/punchblock/connection/asterisk.rb +31 -4
- data/lib/punchblock/connection/xmpp.rb +6 -14
- data/lib/punchblock/core_ext/blather/stanza.rb +1 -1
- data/lib/punchblock/event/active_speaker.rb +2 -10
- data/lib/punchblock/event/answered.rb +3 -3
- data/lib/punchblock/event/asterisk/ami/event.rb +15 -47
- data/lib/punchblock/event/complete.rb +26 -48
- data/lib/punchblock/event/dtmf.rb +3 -13
- data/lib/punchblock/event/end.rb +10 -11
- data/lib/punchblock/event/joined.rb +5 -25
- data/lib/punchblock/event/offer.rb +4 -25
- data/lib/punchblock/event/ringing.rb +3 -3
- data/lib/punchblock/event/unjoined.rb +5 -25
- data/lib/punchblock/event.rb +0 -10
- data/lib/punchblock/has_headers.rb +20 -26
- data/lib/punchblock/rayo_node.rb +46 -23
- data/lib/punchblock/ref.rb +39 -18
- data/lib/punchblock/translator/asterisk/agi_app.rb +15 -0
- data/lib/punchblock/translator/asterisk/agi_command.rb +3 -1
- data/lib/punchblock/translator/asterisk/ami_error_converter.rb +20 -0
- data/lib/punchblock/translator/asterisk/call.rb +60 -39
- data/lib/punchblock/translator/asterisk/channel.rb +41 -0
- data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +4 -1
- data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +4 -4
- data/lib/punchblock/translator/asterisk/component/composed_prompt.rb +62 -0
- data/lib/punchblock/translator/asterisk/component/input.rb +1 -0
- data/lib/punchblock/translator/asterisk/component/mrcp_native_prompt.rb +56 -0
- data/lib/punchblock/translator/asterisk/component/mrcp_prompt.rb +53 -0
- data/lib/punchblock/translator/asterisk/component/mrcp_recog_prompt.rb +99 -0
- data/lib/punchblock/translator/asterisk/component/output.rb +30 -22
- data/lib/punchblock/translator/asterisk/component/record.rb +8 -6
- data/lib/punchblock/translator/asterisk/component.rb +6 -5
- data/lib/punchblock/translator/asterisk/unimrcp_app.rb +26 -0
- data/lib/punchblock/translator/asterisk.rb +24 -28
- data/lib/punchblock/translator/dtmf_recognizer.rb +39 -20
- data/lib/punchblock/translator/freeswitch/call.rb +15 -14
- data/lib/punchblock/translator/freeswitch/component/abstract_output.rb +5 -4
- data/lib/punchblock/translator/freeswitch/component/flite_output.rb +1 -1
- data/lib/punchblock/translator/freeswitch/component/input.rb +5 -0
- data/lib/punchblock/translator/freeswitch/component/output.rb +2 -2
- data/lib/punchblock/translator/freeswitch/component/record.rb +19 -13
- data/lib/punchblock/translator/freeswitch/component/tts_output.rb +2 -2
- data/lib/punchblock/translator/freeswitch/component.rb +2 -5
- data/lib/punchblock/translator/freeswitch.rb +2 -2
- data/lib/punchblock/translator/input_component.rb +33 -13
- data/lib/punchblock/uri_list.rb +21 -0
- data/lib/punchblock/version.rb +1 -1
- data/lib/punchblock.rb +4 -3
- data/punchblock.gemspec +7 -3
- data/spec/punchblock/client/component_registry_spec.rb +1 -1
- data/spec/punchblock/client_spec.rb +10 -26
- data/spec/punchblock/command/accept_spec.rb +41 -7
- data/spec/punchblock/command/answer_spec.rb +51 -7
- data/spec/punchblock/command/dial_spec.rb +56 -14
- data/spec/punchblock/command/hangup_spec.rb +41 -7
- data/spec/punchblock/command/join_spec.rb +53 -11
- data/spec/punchblock/command/mute_spec.rb +19 -4
- data/spec/punchblock/command/redirect_spec.rb +40 -10
- data/spec/punchblock/command/reject_spec.rb +43 -11
- data/spec/punchblock/command/unjoin_spec.rb +40 -9
- data/spec/punchblock/command/unmute_spec.rb +19 -4
- data/spec/punchblock/command_node_spec.rb +0 -4
- data/spec/punchblock/component/asterisk/agi/command_spec.rb +16 -39
- data/spec/punchblock/component/asterisk/ami/action_spec.rb +50 -53
- data/spec/punchblock/component/component_node_spec.rb +3 -5
- data/spec/punchblock/component/input_spec.rb +194 -61
- data/spec/punchblock/component/output_spec.rb +194 -62
- data/spec/punchblock/component/prompt_spec.rb +132 -0
- data/spec/punchblock/component/record_spec.rb +70 -32
- data/spec/punchblock/connection/asterisk_spec.rb +17 -3
- data/spec/punchblock/connection/freeswitch_spec.rb +4 -4
- data/spec/punchblock/connection/xmpp_spec.rb +20 -38
- data/spec/punchblock/event/answered_spec.rb +12 -10
- data/spec/punchblock/event/asterisk/ami/event_spec.rb +27 -22
- data/spec/punchblock/event/complete_spec.rb +15 -19
- data/spec/punchblock/event/dtmf_spec.rb +5 -6
- data/spec/punchblock/event/end_spec.rb +20 -10
- data/spec/punchblock/event/joined_spec.rb +8 -7
- data/spec/punchblock/event/offer_spec.rb +41 -12
- data/spec/punchblock/event/ringing_spec.rb +12 -10
- data/spec/punchblock/event/started_speaking_spec.rb +5 -6
- data/spec/punchblock/event/stopped_speaking_spec.rb +5 -6
- data/spec/punchblock/event/unjoined_spec.rb +7 -7
- data/spec/punchblock/ref_spec.rb +86 -9
- data/spec/punchblock/translator/asterisk/call_spec.rb +317 -154
- data/spec/punchblock/translator/asterisk/component/asterisk/agi_command_spec.rb +28 -5
- data/spec/punchblock/translator/asterisk/component/asterisk/ami_action_spec.rb +15 -13
- data/spec/punchblock/translator/asterisk/component/composed_prompt_spec.rb +237 -0
- data/spec/punchblock/translator/asterisk/component/input_spec.rb +171 -14
- data/spec/punchblock/translator/asterisk/component/mrcp_native_prompt_spec.rb +652 -0
- data/spec/punchblock/translator/asterisk/component/mrcp_prompt_spec.rb +646 -0
- data/spec/punchblock/translator/asterisk/component/output_spec.rb +127 -77
- data/spec/punchblock/translator/asterisk/component/record_spec.rb +17 -8
- data/spec/punchblock/translator/asterisk/component/stop_by_redirect_spec.rb +2 -2
- data/spec/punchblock/translator/asterisk/component_spec.rb +3 -7
- data/spec/punchblock/translator/asterisk_spec.rb +20 -24
- data/spec/punchblock/translator/freeswitch/call_spec.rb +103 -99
- data/spec/punchblock/translator/freeswitch/component/flite_output_spec.rb +17 -8
- data/spec/punchblock/translator/freeswitch/component/input_spec.rb +26 -14
- data/spec/punchblock/translator/freeswitch/component/output_spec.rb +30 -52
- data/spec/punchblock/translator/freeswitch/component/record_spec.rb +23 -19
- data/spec/punchblock/translator/freeswitch/component/tts_output_spec.rb +18 -8
- data/spec/punchblock/translator/freeswitch/component_spec.rb +4 -8
- data/spec/punchblock/translator/freeswitch_spec.rb +11 -14
- data/spec/punchblock/uri_list_spec.rb +49 -0
- data/spec/punchblock_spec.rb +11 -1
- data/spec/spec_helper.rb +7 -11
- data/spec/support/mock_connection_with_event_handler.rb +1 -1
- metadata +104 -24
- data/lib/punchblock/header.rb +0 -9
- data/lib/punchblock/key_value_pair_node.rb +0 -51
- data/spec/punchblock/header_spec.rb +0 -11
|
@@ -5,174 +5,130 @@ module Punchblock
|
|
|
5
5
|
class Output < ComponentNode
|
|
6
6
|
register :output, :output
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def self.new(options = {})
|
|
31
|
-
super().tap do |new_node|
|
|
32
|
-
case options
|
|
33
|
-
when Hash
|
|
34
|
-
new_node.ssml = options.delete(:ssml) if options[:ssml]
|
|
35
|
-
new_node << options.delete(:text) if options[:text]
|
|
36
|
-
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
37
|
-
when Nokogiri::XML::Element
|
|
38
|
-
new_node.inherit options
|
|
8
|
+
class Document < RayoNode
|
|
9
|
+
register :document, :output
|
|
10
|
+
|
|
11
|
+
SSML_CONTENT_TYPE = 'application/ssml+xml'
|
|
12
|
+
|
|
13
|
+
# @return [String] the URL from which the fetch the grammar
|
|
14
|
+
attribute :url
|
|
15
|
+
|
|
16
|
+
# @return [String] the document content type
|
|
17
|
+
attribute :content_type, String, default: ->(grammar, attribute) { grammar.url ? nil : SSML_CONTENT_TYPE }
|
|
18
|
+
|
|
19
|
+
# @return [String, RubySpeech::SSML::Speak, URIList] the document
|
|
20
|
+
attribute :value
|
|
21
|
+
|
|
22
|
+
def inherit(xml_node)
|
|
23
|
+
super
|
|
24
|
+
self.value = if ssml?
|
|
25
|
+
RubySpeech::SSML.import xml_node.content
|
|
26
|
+
elsif urilist?
|
|
27
|
+
URIList.import xml_node.content
|
|
28
|
+
else
|
|
29
|
+
xml_node.content
|
|
39
30
|
end
|
|
31
|
+
self
|
|
40
32
|
end
|
|
41
|
-
end
|
|
42
33
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
34
|
+
def rayo_attributes
|
|
35
|
+
{
|
|
36
|
+
'url' => url,
|
|
37
|
+
'content-type' => content_type
|
|
38
|
+
}
|
|
39
|
+
end
|
|
49
40
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
write_attr :voice, voice
|
|
55
|
-
end
|
|
41
|
+
def rayo_children(root)
|
|
42
|
+
root.cdata xml_value
|
|
43
|
+
super
|
|
44
|
+
end
|
|
56
45
|
|
|
57
|
-
|
|
58
|
-
# @return [String] the SSML document to render TTS
|
|
59
|
-
#
|
|
60
|
-
def ssml
|
|
61
|
-
node = children.first
|
|
62
|
-
RubySpeech::SSML.import node if node
|
|
63
|
-
end
|
|
46
|
+
private
|
|
64
47
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
48
|
+
def xml_value
|
|
49
|
+
if ssml?
|
|
50
|
+
value.to_xml
|
|
51
|
+
elsif urilist?
|
|
52
|
+
value.to_s
|
|
53
|
+
elsif
|
|
54
|
+
value
|
|
55
|
+
end
|
|
72
56
|
end
|
|
73
|
-
self << ssml
|
|
74
|
-
end
|
|
75
57
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def interrupt_on
|
|
80
|
-
read_attr :'interrupt-on', :to_sym
|
|
81
|
-
end
|
|
58
|
+
def ssml?
|
|
59
|
+
content_type == SSML_CONTENT_TYPE
|
|
60
|
+
end
|
|
82
61
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def interrupt_on=(other)
|
|
87
|
-
write_attr :'interrupt-on', other
|
|
62
|
+
def urilist?
|
|
63
|
+
content_type == 'text/uri-list'
|
|
64
|
+
end
|
|
88
65
|
end
|
|
89
66
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
read_attr :'start-offset', :to_i
|
|
67
|
+
def inherit(xml_node)
|
|
68
|
+
document_nodes = xml_node.xpath 'ns:document', ns: self.class.registered_ns
|
|
69
|
+
self.render_documents = document_nodes.to_a.map { |node| Document.from_xml node }
|
|
70
|
+
super
|
|
95
71
|
end
|
|
96
72
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
#
|
|
100
|
-
def start_offset=(other)
|
|
101
|
-
write_attr :'start-offset', other, :to_i
|
|
102
|
-
end
|
|
73
|
+
# @return [String] the TTS voice to use
|
|
74
|
+
attribute :voice, String
|
|
103
75
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
#
|
|
107
|
-
def start_paused
|
|
108
|
-
read_attr(:'start-paused') == 'true'
|
|
109
|
-
end
|
|
76
|
+
# @return [Symbol] input type on which to interrupt output
|
|
77
|
+
attribute :interrupt_on, Symbol
|
|
110
78
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
#
|
|
114
|
-
def start_paused=(other)
|
|
115
|
-
write_attr :'start-paused', other, :to_s
|
|
116
|
-
end
|
|
79
|
+
# @return [Integer] Indicates some offset through which the output should be skipped before rendering begins.
|
|
80
|
+
attribute :start_offset, Integer
|
|
117
81
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
#
|
|
121
|
-
def repeat_interval
|
|
122
|
-
read_attr :'repeat-interval', :to_i
|
|
123
|
-
end
|
|
82
|
+
# @return [true, false] Indicates wether or not the component should be started in a paused state to be resumed at a later time.
|
|
83
|
+
attribute :start_paused, Boolean, default: false
|
|
124
84
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
#
|
|
128
|
-
def repeat_interval=(other)
|
|
129
|
-
write_attr :'repeat-interval', other, :to_i
|
|
130
|
-
end
|
|
85
|
+
# @return [Integer] Indicates the duration of silence that should space repeats of the rendered document.
|
|
86
|
+
attribute :repeat_interval, Integer
|
|
131
87
|
|
|
132
|
-
##
|
|
133
88
|
# @return [Integer] Indicates the number of times the output should be played.
|
|
134
|
-
|
|
135
|
-
def repeat_times
|
|
136
|
-
read_attr :'repeat-times', :to_i
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
##
|
|
140
|
-
# @param [Integer] other Indicates the number of times the output should be played.
|
|
141
|
-
#
|
|
142
|
-
def repeat_times=(other)
|
|
143
|
-
write_attr :'repeat-times', other, :to_i
|
|
144
|
-
end
|
|
89
|
+
attribute :repeat_times, Integer
|
|
145
90
|
|
|
146
|
-
##
|
|
147
91
|
# @return [Integer] Indicates the maximum amount of time for which the output should be allowed to run before being terminated. Includes repeats.
|
|
148
|
-
|
|
149
|
-
def max_time
|
|
150
|
-
read_attr :'max-time', :to_i
|
|
151
|
-
end
|
|
92
|
+
attribute :max_time, Integer
|
|
152
93
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
def
|
|
157
|
-
|
|
94
|
+
# @return [String] the rendering engine requested by the component
|
|
95
|
+
attribute :renderer, String
|
|
96
|
+
|
|
97
|
+
def rayo_attributes
|
|
98
|
+
{
|
|
99
|
+
'voice' => voice,
|
|
100
|
+
'interrupt-on' => interrupt_on,
|
|
101
|
+
'start-offset' => start_offset,
|
|
102
|
+
'start-paused' => start_paused,
|
|
103
|
+
'repeat-interval' => repeat_interval,
|
|
104
|
+
'repeat-times' => repeat_times,
|
|
105
|
+
'max-time' => max_time,
|
|
106
|
+
'renderer' => renderer
|
|
107
|
+
}
|
|
158
108
|
end
|
|
159
109
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
110
|
+
def rayo_children(root)
|
|
111
|
+
render_documents.each do |render_document|
|
|
112
|
+
render_document.to_rayo root.parent
|
|
113
|
+
end
|
|
114
|
+
super
|
|
165
115
|
end
|
|
166
116
|
|
|
117
|
+
# @return [Document] the document to render
|
|
118
|
+
attribute :render_documents, Array[Document], default: []
|
|
119
|
+
|
|
167
120
|
##
|
|
168
|
-
# @param [
|
|
121
|
+
# @param [Hash] other
|
|
122
|
+
# @option other [String] :content_type the document content type
|
|
123
|
+
# @option other [String] :value the output doucment
|
|
124
|
+
# @option other [String] :url the url from which to fetch the document
|
|
169
125
|
#
|
|
170
|
-
def
|
|
171
|
-
|
|
126
|
+
def render_document=(other)
|
|
127
|
+
self.render_documents = [other].compact
|
|
172
128
|
end
|
|
173
129
|
|
|
174
|
-
def
|
|
175
|
-
|
|
130
|
+
def ssml=(other)
|
|
131
|
+
self.render_documents = [{:value => other}]
|
|
176
132
|
end
|
|
177
133
|
|
|
178
134
|
state_machine :state do
|
|
@@ -281,20 +237,8 @@ module Punchblock
|
|
|
281
237
|
class Seek < CommandNode # :nodoc:
|
|
282
238
|
register :seek, :output
|
|
283
239
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
new_node.direction = options[:direction]
|
|
287
|
-
new_node.amount = options[:amount]
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
def direction=(other)
|
|
292
|
-
write_attr :direction, other
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
def amount=(other)
|
|
296
|
-
write_attr :amount, other
|
|
297
|
-
end
|
|
240
|
+
attribute :direction
|
|
241
|
+
attribute :amount
|
|
298
242
|
|
|
299
243
|
def request!
|
|
300
244
|
source.seeking!
|
|
@@ -305,6 +249,10 @@ module Punchblock
|
|
|
305
249
|
source.stopped_seeking!
|
|
306
250
|
super
|
|
307
251
|
end
|
|
252
|
+
|
|
253
|
+
def rayo_attributes
|
|
254
|
+
{'direction' => direction, 'amount' => amount}
|
|
255
|
+
end
|
|
308
256
|
end
|
|
309
257
|
|
|
310
258
|
##
|
|
@@ -496,8 +444,12 @@ module Punchblock
|
|
|
496
444
|
end
|
|
497
445
|
|
|
498
446
|
class Complete
|
|
499
|
-
class
|
|
500
|
-
register :
|
|
447
|
+
class Finish < Event::Complete::Reason
|
|
448
|
+
register :finish, :output_complete
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
class MaxTime < Event::Complete::Reason
|
|
452
|
+
register :'max-time', :output_complete
|
|
501
453
|
end
|
|
502
454
|
end
|
|
503
455
|
end # Output
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Punchblock
|
|
4
|
+
module Component
|
|
5
|
+
class Prompt < ComponentNode
|
|
6
|
+
register :prompt, :prompt
|
|
7
|
+
|
|
8
|
+
attribute :barge_in, Boolean
|
|
9
|
+
attribute :output, Output
|
|
10
|
+
attribute :input, Input
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Create a prompt command
|
|
14
|
+
#
|
|
15
|
+
# @param [Output] output
|
|
16
|
+
# @param [Input] input
|
|
17
|
+
# @param [Hash] options
|
|
18
|
+
# @option options [true, false, optional] :barge_in Indicates wether or not the input should interrupt then output
|
|
19
|
+
#
|
|
20
|
+
# @return [Component::Prompt] a formatted Rayo prompt command
|
|
21
|
+
#
|
|
22
|
+
def initialize(output = nil, input = nil, options = {})
|
|
23
|
+
super options
|
|
24
|
+
self.output = output
|
|
25
|
+
self.input = input
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def inherit(xml_node)
|
|
29
|
+
input_node = xml_node.at_xpath('ns:input', ns: Input.registered_ns)
|
|
30
|
+
self.input = Input.from_xml input_node if input_node
|
|
31
|
+
|
|
32
|
+
output_node = xml_node.at_xpath('ns:output', ns: Output.registered_ns)
|
|
33
|
+
self.output = Output.from_xml output_node if output_node
|
|
34
|
+
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def rayo_attributes
|
|
39
|
+
{
|
|
40
|
+
'barge-in' => barge_in
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def rayo_children(root)
|
|
45
|
+
input.to_rayo(root) if input
|
|
46
|
+
output.to_rayo(root) if output
|
|
47
|
+
super
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -7,132 +7,51 @@ module Punchblock
|
|
|
7
7
|
|
|
8
8
|
VALID_DIRECTIONS = [:duplex, :send, :recv].freeze
|
|
9
9
|
|
|
10
|
-
##
|
|
11
|
-
# Creates an Rayo Record command
|
|
12
|
-
#
|
|
13
|
-
# @param [Hash] options
|
|
14
|
-
# @option options [String] :format to use for recording
|
|
15
|
-
# @option options [Integer] :initial_timeout Controls how long the recognizer should wait after the end of the prompt for the caller to speak before sending a Recorder event.
|
|
16
|
-
# @option options [Integer] :final_timeout Controls the length of a period of silence after callers have spoken to conclude they finished.
|
|
17
|
-
# @option options [Integer] :max_duration Indicates the maximum duration for the recording.
|
|
18
|
-
# @option options [true, false] :start_beep Indicates whether subsequent record will be preceded with a beep.
|
|
19
|
-
# @option options [true, false] :start_paused Whether subsequent record will start in PAUSE mode.
|
|
20
|
-
#
|
|
21
|
-
# @return [Command::Record] a Rayo "record" command
|
|
22
|
-
#
|
|
23
|
-
# @example
|
|
24
|
-
# record :text => 'Hello brown cow.'
|
|
25
|
-
#
|
|
26
|
-
# returns:
|
|
27
|
-
# <record xmlns="urn:xmpp:rayo:record:1">Hello brown cow.</record>
|
|
28
|
-
#
|
|
29
|
-
def self.new(options = {})
|
|
30
|
-
super().tap do |new_node|
|
|
31
|
-
options.each_pair { |k,v| new_node.send :"#{k}=", v }
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
##
|
|
36
|
-
# @return [Integer] Controls the length of a period of silence after callers have spoken to conclude they finished.
|
|
37
|
-
#
|
|
38
|
-
def final_timeout
|
|
39
|
-
read_attr :'final-timeout', :to_i
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
##
|
|
43
|
-
# @param [Integer] timeout Controls the length of a period of silence after callers have spoken to conclude they finished.
|
|
44
|
-
#
|
|
45
|
-
def final_timeout=(timeout)
|
|
46
|
-
write_attr :'final-timeout', timeout, :to_i
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
##
|
|
50
10
|
# @return [String] the codec to use for recording
|
|
51
|
-
|
|
52
|
-
def format
|
|
53
|
-
read_attr :format
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
##
|
|
57
|
-
# @param [String] codec to use for recording
|
|
58
|
-
#
|
|
59
|
-
def format=(format)
|
|
60
|
-
write_attr :format, format
|
|
61
|
-
end
|
|
11
|
+
attribute :format
|
|
62
12
|
|
|
63
|
-
##
|
|
64
13
|
# @return [Integer] Controls how long the recognizer should wait after the end of the prompt for the caller to speak before sending a Recorder event.
|
|
65
|
-
|
|
66
|
-
def initial_timeout
|
|
67
|
-
read_attr :'initial-timeout', :to_i
|
|
68
|
-
end
|
|
14
|
+
attribute :initial_timeout, Integer
|
|
69
15
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
#
|
|
73
|
-
def initial_timeout=(timeout)
|
|
74
|
-
write_attr :'initial-timeout', timeout, :to_i
|
|
75
|
-
end
|
|
16
|
+
# @return [Integer] Controls the length of a period of silence after callers have spoken to conclude they finished.
|
|
17
|
+
attribute :final_timeout, Integer
|
|
76
18
|
|
|
77
|
-
##
|
|
78
19
|
# @return [Integer] Indicates the maximum duration for the recording.
|
|
79
|
-
|
|
80
|
-
def max_duration
|
|
81
|
-
read_attr :'max-duration', :to_i
|
|
82
|
-
end
|
|
20
|
+
attribute :max_duration, Integer
|
|
83
21
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
#
|
|
87
|
-
def max_duration=(other)
|
|
88
|
-
write_attr :'max-duration', other, :to_i
|
|
89
|
-
end
|
|
22
|
+
# @return [true, false] Indicates whether record will be preceded with a beep.
|
|
23
|
+
attribute :start_beep, Boolean
|
|
90
24
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
#
|
|
94
|
-
def start_beep
|
|
95
|
-
read_attr(:'start-beep') == 'true'
|
|
96
|
-
end
|
|
25
|
+
# @return [true, false] Indicates whether record will be followed by a beep.
|
|
26
|
+
attribute :stop_beep, Boolean
|
|
97
27
|
|
|
98
|
-
##
|
|
99
|
-
# @param [true, false] sb Indicates whether subsequent record will be preceded with a beep.
|
|
100
|
-
#
|
|
101
|
-
def start_beep=(sb)
|
|
102
|
-
write_attr :'start-beep', sb
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
##
|
|
106
28
|
# @return [true, false] Whether subsequent record will start in PAUSE mode.
|
|
107
|
-
|
|
108
|
-
def start_paused
|
|
109
|
-
read_attr(:'start-paused') == 'true'
|
|
110
|
-
end
|
|
29
|
+
attribute :start_paused, Boolean
|
|
111
30
|
|
|
112
|
-
##
|
|
113
|
-
# @param [true, false] other Whether subsequent record will start in PAUSE mode.
|
|
114
|
-
#
|
|
115
|
-
def start_paused=(other)
|
|
116
|
-
write_attr :'start-paused', other
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
##
|
|
120
31
|
# @return [Symbol] the direction of media to be recorded.
|
|
121
|
-
|
|
122
|
-
read_attr :direction, :to_sym
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
##
|
|
126
|
-
# @param [#to_s] otherthe direction of media to be recorded. Can be :duplex, :recv or :send
|
|
32
|
+
attribute :direction, Symbol
|
|
127
33
|
def direction=(direction)
|
|
128
34
|
if direction && !VALID_DIRECTIONS.include?(direction.to_sym)
|
|
129
35
|
raise ArgumentError, "Invalid Direction (#{direction}), use: #{VALID_DIRECTIONS*' '}"
|
|
130
36
|
end
|
|
131
|
-
|
|
37
|
+
super
|
|
132
38
|
end
|
|
133
39
|
|
|
134
|
-
|
|
135
|
-
|
|
40
|
+
# @return [true, false] wether to mix audio down or not
|
|
41
|
+
attribute :mix, Boolean
|
|
42
|
+
|
|
43
|
+
def rayo_attributes
|
|
44
|
+
{
|
|
45
|
+
'format' => format,
|
|
46
|
+
'initial-timeout' => initial_timeout,
|
|
47
|
+
'final-timeout' => final_timeout,
|
|
48
|
+
'max-duration' => max_duration,
|
|
49
|
+
'start-beep' => start_beep,
|
|
50
|
+
'stop-beep' => start_beep,
|
|
51
|
+
'start-paused' => start_paused,
|
|
52
|
+
'direction' => direction,
|
|
53
|
+
'mix' => mix
|
|
54
|
+
}
|
|
136
55
|
end
|
|
137
56
|
|
|
138
57
|
state_machine :state do
|
|
@@ -221,32 +140,24 @@ module Punchblock
|
|
|
221
140
|
class Recording < Event
|
|
222
141
|
register :recording, :record_complete
|
|
223
142
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def uri=(other)
|
|
229
|
-
write_attr :uri, other
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def duration
|
|
233
|
-
read_attr :duration, :to_i
|
|
234
|
-
end
|
|
143
|
+
attribute :uri
|
|
144
|
+
attribute :duration, Integer
|
|
145
|
+
attribute :size, Integer
|
|
146
|
+
end
|
|
235
147
|
|
|
236
|
-
|
|
237
|
-
|
|
148
|
+
class Complete
|
|
149
|
+
class MaxDuration < Event::Complete::Reason
|
|
150
|
+
register :'max-duration', :record_complete
|
|
238
151
|
end
|
|
239
152
|
|
|
240
|
-
|
|
241
|
-
|
|
153
|
+
class InitialTimeout < Event::Complete::Reason
|
|
154
|
+
register :'initial-timeout', :record_complete
|
|
242
155
|
end
|
|
243
|
-
end
|
|
244
156
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
register :success, :record_complete
|
|
157
|
+
class FinalTimeout < Event::Complete::Reason
|
|
158
|
+
register :'final-timeout', :record_complete
|
|
248
159
|
end
|
|
249
160
|
end
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
data/lib/punchblock/component.rb
CHANGED
|
@@ -9,14 +9,15 @@ module Punchblock
|
|
|
9
9
|
attr_accessor :event_handler
|
|
10
10
|
|
|
11
11
|
def initialize(options = {})
|
|
12
|
-
@
|
|
13
|
-
@
|
|
12
|
+
@stream_options = options.values_at(:host, :port, :username, :password)
|
|
13
|
+
@translator_options = options.values_at(:media_engine)
|
|
14
|
+
@ami_client = new_ami_stream
|
|
15
|
+
@translator = Translator::Asterisk.new @ami_client, self, *@translator_options
|
|
14
16
|
super()
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def run
|
|
18
|
-
|
|
19
|
-
Celluloid::Actor.join(ami_client)
|
|
20
|
+
start_ami_client
|
|
20
21
|
raise DisconnectedError
|
|
21
22
|
end
|
|
22
23
|
|
|
@@ -32,6 +33,32 @@ module Punchblock
|
|
|
32
33
|
def handle_event(event)
|
|
33
34
|
event_handler.call event
|
|
34
35
|
end
|
|
36
|
+
|
|
37
|
+
def new_ami_stream
|
|
38
|
+
stream = RubyAMI::Stream.new(*@stream_options, ->(event) { translator.async.handle_ami_event event }, pb_logger)
|
|
39
|
+
client = (ami_client || RubyAMIStreamProxy.new(stream))
|
|
40
|
+
client.stream = stream
|
|
41
|
+
client
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def start_ami_client
|
|
45
|
+
@ami_client = new_ami_stream unless ami_client.alive?
|
|
46
|
+
ami_client.async.run
|
|
47
|
+
Celluloid::Actor.join(ami_client)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class RubyAMIStreamProxy
|
|
52
|
+
attr_accessor :stream
|
|
53
|
+
|
|
54
|
+
def initialize(ami)
|
|
55
|
+
@stream = ami
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def method_missing(method, *args, &block)
|
|
59
|
+
stream.__send__(method, *args, &block)
|
|
60
|
+
end
|
|
61
|
+
|
|
35
62
|
end
|
|
36
63
|
end
|
|
37
64
|
end
|