punchblock 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/lib/punchblock.rb +1 -1
- data/lib/punchblock/connection.rb +1 -0
- data/lib/punchblock/connection/asterisk.rb +0 -1
- data/lib/punchblock/connection/freeswitch.rb +49 -0
- data/lib/punchblock/event/offer.rb +1 -1
- data/lib/punchblock/translator.rb +5 -0
- data/lib/punchblock/translator/asterisk.rb +16 -28
- data/lib/punchblock/translator/asterisk/call.rb +4 -21
- data/lib/punchblock/translator/asterisk/component.rb +0 -5
- data/lib/punchblock/translator/asterisk/component/asterisk/agi_command.rb +0 -3
- data/lib/punchblock/translator/asterisk/component/asterisk/ami_action.rb +0 -1
- data/lib/punchblock/translator/asterisk/component/input.rb +7 -97
- data/lib/punchblock/translator/asterisk/component/output.rb +0 -4
- data/lib/punchblock/translator/asterisk/component/record.rb +0 -2
- data/lib/punchblock/translator/freeswitch.rb +153 -0
- data/lib/punchblock/translator/freeswitch/call.rb +265 -0
- data/lib/punchblock/translator/freeswitch/component.rb +92 -0
- data/lib/punchblock/translator/freeswitch/component/abstract_output.rb +57 -0
- data/lib/punchblock/translator/freeswitch/component/flite_output.rb +17 -0
- data/lib/punchblock/translator/freeswitch/component/input.rb +29 -0
- data/lib/punchblock/translator/freeswitch/component/output.rb +56 -0
- data/lib/punchblock/translator/freeswitch/component/record.rb +79 -0
- data/lib/punchblock/translator/freeswitch/component/tts_output.rb +26 -0
- data/lib/punchblock/translator/input_component.rb +108 -0
- data/lib/punchblock/version.rb +1 -1
- data/punchblock.gemspec +3 -2
- data/spec/punchblock/connection/freeswitch_spec.rb +90 -0
- data/spec/punchblock/translator/asterisk/call_spec.rb +23 -2
- data/spec/punchblock/translator/asterisk/component/input_spec.rb +3 -3
- data/spec/punchblock/translator/asterisk_spec.rb +1 -1
- data/spec/punchblock/translator/freeswitch/call_spec.rb +922 -0
- data/spec/punchblock/translator/freeswitch/component/flite_output_spec.rb +279 -0
- data/spec/punchblock/translator/freeswitch/component/input_spec.rb +312 -0
- data/spec/punchblock/translator/freeswitch/component/output_spec.rb +369 -0
- data/spec/punchblock/translator/freeswitch/component/record_spec.rb +373 -0
- data/spec/punchblock/translator/freeswitch/component/tts_output_spec.rb +285 -0
- data/spec/punchblock/translator/freeswitch/component_spec.rb +118 -0
- data/spec/punchblock/translator/freeswitch_spec.rb +597 -0
- data/spec/punchblock_spec.rb +11 -0
- data/spec/spec_helper.rb +1 -0
- metadata +52 -7
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# [develop](https://github.com/adhearsion/punchblock)
|
2
2
|
|
3
|
+
# [v1.4.0](https://github.com/adhearsion/punchblock/compare/v1.3.0...v1.4.0) - [2012-08-07](https://rubygems.org/gems/punchblock/versions/1.4.0)
|
4
|
+
* Feature: FreeSWITCH support (mostly complete, experimental, proceed with caution)
|
5
|
+
* Bugfix: Report the correct caller ID in offers from Asterisk
|
6
|
+
* Bugfix: Strip out caller ID name from dial commands on Asterisk
|
7
|
+
|
3
8
|
# [v1.3.0](https://github.com/adhearsion/punchblock/compare/v1.2.0...v1.3.0) - [2012-07-22](https://rubygems.org/gems/punchblock/versions/1.3.0)
|
4
9
|
* Change: Asterisk output now uses Playback rather than STREAM FILE
|
5
10
|
* Feature: The recordings dir is now checked for existence on startup, and logs an error if it is not there. Asterisk only.
|
data/lib/punchblock.rb
CHANGED
@@ -44,7 +44,7 @@ module Punchblock
|
|
44
44
|
#
|
45
45
|
# Get a new Punchblock client with a connection attached
|
46
46
|
#
|
47
|
-
# @param [Symbol] type the connection type (eg :XMPP, :asterisk)
|
47
|
+
# @param [Symbol] type the connection type (eg :XMPP, :asterisk, :freeswitch)
|
48
48
|
# @param [Hash] options the options to pass to the connection (credentials, etc
|
49
49
|
#
|
50
50
|
# @return [Punchblock::Client] a punchblock client object
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'ruby_fs'
|
4
|
+
|
5
|
+
module Punchblock
|
6
|
+
module Connection
|
7
|
+
class Freeswitch < GenericConnection
|
8
|
+
attr_reader :translator, :stream
|
9
|
+
attr_accessor :event_handler
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@translator = Translator::Freeswitch.new self, options[:media_engine], options[:default_voice]
|
13
|
+
@stream_options = options.values_at(:host, :port, :password)
|
14
|
+
@stream = new_fs_stream
|
15
|
+
super()
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
pb_logger.debug "Starting the RubyFS stream"
|
20
|
+
start_stream
|
21
|
+
raise DisconnectedError
|
22
|
+
end
|
23
|
+
|
24
|
+
def stop
|
25
|
+
stream.shutdown
|
26
|
+
translator.terminate
|
27
|
+
end
|
28
|
+
|
29
|
+
def write(command, options)
|
30
|
+
translator.execute_command! command, options
|
31
|
+
end
|
32
|
+
|
33
|
+
def handle_event(event)
|
34
|
+
event_handler.call event if event_handler.respond_to?(:call)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def new_fs_stream
|
40
|
+
RubyFS::Stream.new(*@stream_options, lambda { |e| translator.handle_es_event! e })
|
41
|
+
end
|
42
|
+
|
43
|
+
def start_stream
|
44
|
+
@stream = new_fs_stream unless @stream.alive?
|
45
|
+
@stream.run
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -28,7 +28,7 @@ module Punchblock
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def inspect
|
31
|
-
"#<Punchblock::Event::Offer to=\"#{to}\", from=\"#{from}\", call_id=\"#{target_call_id}\""
|
31
|
+
"#<Punchblock::Event::Offer to=\"#{to}\", from=\"#{from}\", headers=#{headers_hash.inspect}, call_id=\"#{target_call_id}\""
|
32
32
|
end
|
33
33
|
end # Offer
|
34
34
|
end
|
@@ -22,7 +22,6 @@ module Punchblock
|
|
22
22
|
trap_exit :actor_died
|
23
23
|
|
24
24
|
def initialize(ami_client, connection, media_engine = nil)
|
25
|
-
pb_logger.debug "Starting up..."
|
26
25
|
@ami_client, @connection, @media_engine = ami_client, connection, media_engine
|
27
26
|
@calls, @components, @channel_to_call_id = {}, {}, {}
|
28
27
|
@fully_booted_count = 0
|
@@ -55,42 +54,38 @@ module Punchblock
|
|
55
54
|
end
|
56
55
|
|
57
56
|
def shutdown
|
58
|
-
pb_logger.debug "Shutting down"
|
59
57
|
@calls.values.each(&:shutdown!)
|
60
58
|
current_actor.terminate!
|
61
59
|
end
|
62
60
|
|
63
61
|
def handle_ami_event(event)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
@fully_booted_count = 0
|
73
|
-
run_at_fully_booted
|
74
|
-
end
|
75
|
-
return
|
62
|
+
return unless event.is_a? RubyAMI::Event
|
63
|
+
|
64
|
+
if event.name.downcase == "fullybooted"
|
65
|
+
@fully_booted_count += 1
|
66
|
+
if @fully_booted_count >= 2
|
67
|
+
handle_pb_event Connection::Connected.new
|
68
|
+
@fully_booted_count = 0
|
69
|
+
run_at_fully_booted
|
76
70
|
end
|
71
|
+
return
|
72
|
+
end
|
77
73
|
|
78
|
-
|
74
|
+
handle_varset_ami_event event
|
79
75
|
|
80
|
-
|
76
|
+
ami_dispatch_to_or_create_call event
|
81
77
|
|
82
|
-
|
83
|
-
|
84
|
-
end
|
78
|
+
unless ami_event_known_call?(event)
|
79
|
+
handle_pb_event Event::Asterisk::AMI::Event.new(:name => event.name, :attributes => event.headers)
|
85
80
|
end
|
86
81
|
end
|
82
|
+
exclusive :handle_ami_event
|
87
83
|
|
88
84
|
def handle_pb_event(event)
|
89
85
|
connection.handle_event event
|
90
86
|
end
|
91
87
|
|
92
88
|
def execute_command(command, options = {})
|
93
|
-
pb_logger.trace "Executing command #{command.inspect}"
|
94
89
|
command.request!
|
95
90
|
|
96
91
|
command.target_call_id ||= options[:call_id]
|
@@ -144,7 +139,6 @@ module Punchblock
|
|
144
139
|
send_ami_action('Command', {
|
145
140
|
'Command' => "dialplan add extension #{REDIRECT_EXTENSION},#{REDIRECT_PRIORITY},AGI,agi:async into #{REDIRECT_CONTEXT}"
|
146
141
|
})
|
147
|
-
pb_logger.trace "Added extension extension #{REDIRECT_EXTENSION},#{REDIRECT_PRIORITY},AGI,agi:async into #{REDIRECT_CONTEXT}"
|
148
142
|
send_ami_action('Command', {
|
149
143
|
'Command' => "dialplan show #{REDIRECT_CONTEXT}"
|
150
144
|
}) do |result|
|
@@ -160,9 +154,7 @@ module Punchblock
|
|
160
154
|
|
161
155
|
def actor_died(actor, reason)
|
162
156
|
return unless reason
|
163
|
-
pb_logger.error "A linked actor (#{actor.inspect}) died due to #{reason.inspect}"
|
164
157
|
if id = @calls.key(actor)
|
165
|
-
pb_logger.info "Dead actor was a call we know about, with ID #{id}. Removing it from the registry..."
|
166
158
|
@calls.delete id
|
167
159
|
end_event = Punchblock::Event::End.new :target_call_id => id,
|
168
160
|
:reason => :error
|
@@ -175,9 +167,7 @@ module Punchblock
|
|
175
167
|
def handle_varset_ami_event(event)
|
176
168
|
return unless event.name == 'VarSet' && event['Variable'] == 'punchblock_call_id' && (call = call_with_id event['Value'])
|
177
169
|
|
178
|
-
pb_logger.trace "Received a VarSet event indicating the full channel for call #{call}"
|
179
170
|
@channel_to_call_id.delete call.channel
|
180
|
-
pb_logger.trace "Removed call with old channel from channel map: #{@channel_to_call_id}"
|
181
171
|
call.channel = event['Channel']
|
182
172
|
register_call call
|
183
173
|
end
|
@@ -206,10 +196,8 @@ module Punchblock
|
|
206
196
|
def handle_async_agi_start_event(event)
|
207
197
|
env = RubyAMI::AsyncAGIEnvironmentParser.new(event['Env']).to_hash
|
208
198
|
|
209
|
-
return
|
210
|
-
return pb_logger.warn "Ignoring AsyncAGI Start event because it is for an 'Kill' type" if env[:agi_type] == 'Kill'
|
199
|
+
return if env[:agi_extension] == 'h' || env[:agi_type] == 'Kill'
|
211
200
|
|
212
|
-
pb_logger.trace "Handling AsyncAGI Start event by creating a new call"
|
213
201
|
call = Call.new event['Channel'], current_actor, env
|
214
202
|
link call
|
215
203
|
register_call call
|
@@ -28,7 +28,6 @@ module Punchblock
|
|
28
28
|
@id, @components = Punchblock.new_uuid, {}
|
29
29
|
@answered = false
|
30
30
|
@pending_joins = {}
|
31
|
-
pb_logger.debug "Starting up call with channel #{channel}, id #{@id}"
|
32
31
|
@progress_sent = false
|
33
32
|
end
|
34
33
|
|
@@ -46,7 +45,6 @@ module Punchblock
|
|
46
45
|
end
|
47
46
|
|
48
47
|
def shutdown
|
49
|
-
pb_logger.debug "Shutting down"
|
50
48
|
current_actor.terminate!
|
51
49
|
end
|
52
50
|
|
@@ -57,10 +55,12 @@ module Punchblock
|
|
57
55
|
|
58
56
|
def dial(dial_command)
|
59
57
|
@direction = :outbound
|
58
|
+
channel = dial_command.to || ''
|
59
|
+
channel.match(/.* <(?<channel>.*)>/) { |m| channel = m[:channel] }
|
60
60
|
params = { :async => true,
|
61
61
|
:application => 'AGI',
|
62
62
|
:data => 'agi:async',
|
63
|
-
:channel =>
|
63
|
+
:channel => channel,
|
64
64
|
:callerid => dial_command.from,
|
65
65
|
:variable => "punchblock_call_id=#{id}"
|
66
66
|
}
|
@@ -87,13 +87,11 @@ module Punchblock
|
|
87
87
|
|
88
88
|
def send_progress
|
89
89
|
return if answered? || outbound? || @progress_sent
|
90
|
-
pb_logger.debug "Sending Progress to start early media"
|
91
90
|
@progress_sent = true
|
92
91
|
send_agi_action "EXEC Progress"
|
93
92
|
end
|
94
93
|
|
95
94
|
def channel=(other)
|
96
|
-
pb_logger.info "Channel is changing from #{channel} to #{other}."
|
97
95
|
@channel = other
|
98
96
|
end
|
99
97
|
|
@@ -102,7 +100,6 @@ module Punchblock
|
|
102
100
|
|
103
101
|
case ami_event.name
|
104
102
|
when 'Hangup'
|
105
|
-
pb_logger.trace "Received a Hangup AMI event. Sending End event."
|
106
103
|
@components.dup.each_pair do |id, component|
|
107
104
|
safe_from_dead_actors do
|
108
105
|
component.call_ended if component.alive?
|
@@ -110,14 +107,10 @@ module Punchblock
|
|
110
107
|
end
|
111
108
|
send_end_event HANGUP_CAUSE_TO_END_REASON[ami_event['Cause'].to_i]
|
112
109
|
when 'AsyncAGI'
|
113
|
-
pb_logger.trace "Received an AsyncAGI event. Looking for matching AGICommand component."
|
114
110
|
if component = component_with_id(ami_event['CommandID'])
|
115
111
|
component.handle_ami_event ami_event
|
116
|
-
else
|
117
|
-
pb_logger.trace "Could not find component for AMI event: #{ami_event.inspect}"
|
118
112
|
end
|
119
113
|
when 'Newstate'
|
120
|
-
pb_logger.trace "Received a Newstate AMI event with state #{ami_event['ChannelState']}: #{ami_event['ChannelStateDesc']}"
|
121
114
|
case ami_event['ChannelState']
|
122
115
|
when '5'
|
123
116
|
send_pb_event Event::Ringing.new
|
@@ -127,7 +120,6 @@ module Punchblock
|
|
127
120
|
end
|
128
121
|
when 'OriginateResponse'
|
129
122
|
if ami_event['Response'] == 'Failure' && ami_event['Uniqueid'] == '<null>'
|
130
|
-
pb_logger.info "Outbound call could not be established!"
|
131
123
|
send_end_event :error
|
132
124
|
end
|
133
125
|
when 'BridgeExec'
|
@@ -162,7 +154,6 @@ module Punchblock
|
|
162
154
|
end
|
163
155
|
|
164
156
|
def execute_command(command)
|
165
|
-
pb_logger.debug "Executing command: #{command.inspect}"
|
166
157
|
if command.component_id
|
167
158
|
if component = component_with_id(command.component_id)
|
168
159
|
component.execute_command command
|
@@ -173,10 +164,8 @@ module Punchblock
|
|
173
164
|
case command
|
174
165
|
when Command::Accept
|
175
166
|
if outbound?
|
176
|
-
pb_logger.trace "Attempting to accept an outbound call. Skipping RINGING."
|
177
167
|
command.response = true
|
178
168
|
else
|
179
|
-
pb_logger.trace "Attempting to accept an inbound call. Executing RINGING."
|
180
169
|
send_agi_action 'EXEC RINGING' do |response|
|
181
170
|
command.response = true
|
182
171
|
end
|
@@ -231,11 +220,9 @@ module Punchblock
|
|
231
220
|
end
|
232
221
|
|
233
222
|
def send_agi_action(command, *params, &block)
|
234
|
-
pb_logger.trace "Sending AGI action #{command}"
|
235
223
|
@current_agi_command = Punchblock::Component::Asterisk::AGI::Command.new :name => command, :params => params, :target_call_id => id
|
236
224
|
@current_agi_command.request!
|
237
225
|
@current_agi_command.register_handler :internal, Punchblock::Event::Complete do |e|
|
238
|
-
pb_logger.trace "AGI action received complete event #{e.inspect}"
|
239
226
|
block.call e if block
|
240
227
|
end
|
241
228
|
execute_component Component::Asterisk::AGICommand, @current_agi_command, :internal => true
|
@@ -244,7 +231,6 @@ module Punchblock
|
|
244
231
|
def send_ami_action(name, headers = {}, &block)
|
245
232
|
(name.is_a?(RubyAMI::Action) ? name : RubyAMI::Action.new(name, headers, &block)).tap do |action|
|
246
233
|
@current_ami_action = action
|
247
|
-
pb_logger.trace "Sending AMI action #{action.inspect}"
|
248
234
|
translator.send_ami_action action
|
249
235
|
end
|
250
236
|
end
|
@@ -271,9 +257,7 @@ module Punchblock
|
|
271
257
|
|
272
258
|
def actor_died(actor, reason)
|
273
259
|
return unless reason
|
274
|
-
pb_logger.error "A linked actor (#{actor.inspect}) died due to #{reason.inspect}"
|
275
260
|
if id = @components.key(actor)
|
276
|
-
pb_logger.info "Dead actor was a component we know about, with ID #{id}. Removing it from the registry..."
|
277
261
|
@components.delete id
|
278
262
|
complete_event = Punchblock::Event::Complete.new :component_id => id, :reason => Punchblock::Event::Complete::Error.new
|
279
263
|
send_pb_event complete_event
|
@@ -298,13 +282,12 @@ module Punchblock
|
|
298
282
|
|
299
283
|
def send_pb_event(event)
|
300
284
|
event.target_call_id = id
|
301
|
-
pb_logger.trace "Sending Punchblock event: #{event.inspect}"
|
302
285
|
translator.handle_pb_event event
|
303
286
|
end
|
304
287
|
|
305
288
|
def offer_event
|
306
289
|
Event::Offer.new :to => agi_env.values_at(:agi_dnid, :agi_extension).detect { |e| e && e != 'unknown' },
|
307
|
-
:from => "#{agi_env[:agi_calleridname]} <#{[agi_env[:agi_type]
|
290
|
+
:from => "#{agi_env[:agi_calleridname]} <#{[agi_env[:agi_type], agi_env[:agi_callerid]].join('/')}>",
|
308
291
|
:headers => sip_headers
|
309
292
|
end
|
310
293
|
|
@@ -13,8 +13,6 @@ module Punchblock
|
|
13
13
|
autoload :StopByRedirect
|
14
14
|
|
15
15
|
class Component
|
16
|
-
OptionError = Class.new Punchblock::Error
|
17
|
-
|
18
16
|
include Celluloid
|
19
17
|
include DeadActorSafety
|
20
18
|
|
@@ -27,7 +25,6 @@ module Punchblock
|
|
27
25
|
@id = Punchblock.new_uuid
|
28
26
|
@complete = false
|
29
27
|
setup
|
30
|
-
pb_logger.debug "Starting up..."
|
31
28
|
end
|
32
29
|
|
33
30
|
def setup
|
@@ -51,7 +48,6 @@ module Punchblock
|
|
51
48
|
def send_event(event)
|
52
49
|
event.component_id = id
|
53
50
|
event.target_call_id = call_id
|
54
|
-
pb_logger.debug "Sending event #{event}"
|
55
51
|
if internal
|
56
52
|
@component_node.add_event event
|
57
53
|
else
|
@@ -74,7 +70,6 @@ module Punchblock
|
|
74
70
|
end
|
75
71
|
|
76
72
|
def set_node_response(value)
|
77
|
-
pb_logger.debug "Setting response on component node to #{value}"
|
78
73
|
@component_node.response = value
|
79
74
|
end
|
80
75
|
|
@@ -20,17 +20,14 @@ module Punchblock
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def handle_ami_event(event)
|
23
|
-
pb_logger.debug "Handling AMI event: #{event.inspect}"
|
24
23
|
if event.name == 'AsyncAGI'
|
25
24
|
if event['SubEvent'] == 'Exec'
|
26
|
-
pb_logger.debug "Received AsyncAGI:Exec event, sending complete event."
|
27
25
|
send_complete_event success_reason(event)
|
28
26
|
end
|
29
27
|
end
|
30
28
|
end
|
31
29
|
|
32
30
|
def handle_response(response)
|
33
|
-
pb_logger.debug "Handling response: #{response.inspect}"
|
34
31
|
case response
|
35
32
|
when RubyAMI::Error
|
36
33
|
set_node_response false
|
@@ -6,114 +6,24 @@ module Punchblock
|
|
6
6
|
module Component
|
7
7
|
class Input < Component
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
def setup
|
12
|
-
@buffer = ""
|
13
|
-
end
|
9
|
+
include InputComponent
|
14
10
|
|
15
11
|
def execute
|
16
12
|
@call.send_progress
|
17
|
-
|
18
|
-
@inter_digit_timeout = @component_node.inter_digit_timeout || -1
|
19
|
-
|
20
|
-
raise OptionError, 'A grammar document is required.' unless @component_node.grammar
|
21
|
-
raise OptionError, 'A mode value other than DTMF is unsupported on Asterisk.' unless @component_node.mode == :dtmf
|
22
|
-
raise OptionError, 'An initial timeout value that is negative (and not -1) is invalid.' unless initial_timeout >= -1
|
23
|
-
raise OptionError, 'An inter-digit timeout value that is negative (and not -1) is invalid.' unless @inter_digit_timeout >= -1
|
24
|
-
|
25
|
-
send_ref
|
26
|
-
|
27
|
-
@grammar = @component_node.grammar.value.clone
|
28
|
-
grammar.inline!
|
29
|
-
grammar.tokenize!
|
30
|
-
grammar.normalize_whitespace
|
31
|
-
|
32
|
-
begin_initial_timer initial_timeout/1000 unless initial_timeout == -1
|
33
|
-
|
34
|
-
component = current_actor
|
35
|
-
|
36
|
-
@dtmf_handler_id = call.register_handler :ami, :name => 'DTMF' do |event|
|
37
|
-
component.process_dtmf! event['Digit'] if event['End'] == 'Yes'
|
38
|
-
end
|
39
|
-
rescue OptionError => e
|
40
|
-
with_error 'option error', e.message
|
41
|
-
end
|
42
|
-
|
43
|
-
def process_dtmf(digit)
|
44
|
-
pb_logger.trace "Processing incoming DTMF digit #{digit}"
|
45
|
-
buffer << digit
|
46
|
-
cancel_initial_timer
|
47
|
-
case (match = grammar.match buffer.dup)
|
48
|
-
when RubySpeech::GRXML::Match
|
49
|
-
pb_logger.trace "Found a match against buffer #{buffer}"
|
50
|
-
complete success_reason(match)
|
51
|
-
when RubySpeech::GRXML::NoMatch
|
52
|
-
pb_logger.trace "Buffer #{buffer} does not match grammar"
|
53
|
-
complete Punchblock::Component::Input::Complete::NoMatch.new
|
54
|
-
when RubySpeech::GRXML::PotentialMatch
|
55
|
-
pb_logger.trace "Buffer #{buffer} potentially matches grammar. Waiting..."
|
56
|
-
reset_inter_digit_timer
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def execute_command(command)
|
61
|
-
case command
|
62
|
-
when Punchblock::Component::Stop
|
63
|
-
command.response = true
|
64
|
-
complete Punchblock::Event::Complete::Stop.new
|
65
|
-
else
|
66
|
-
super
|
67
|
-
end
|
13
|
+
super
|
68
14
|
end
|
69
15
|
|
70
16
|
private
|
71
17
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
complete Punchblock::Component::Input::Complete::NoInput.new
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def cancel_initial_timer
|
81
|
-
return unless instance_variable_defined?(:@initial_timer) && @initial_timer
|
82
|
-
@initial_timer.cancel
|
83
|
-
@initial_timer = nil
|
84
|
-
end
|
85
|
-
|
86
|
-
def reset_inter_digit_timer
|
87
|
-
return if @inter_digit_timeout == -1
|
88
|
-
@inter_digit_timer ||= begin
|
89
|
-
pb_logger.trace "Setting inter-digit timer for #{@inter_digit_timeout/1000} seconds"
|
90
|
-
after @inter_digit_timeout/1000 do
|
91
|
-
pb_logger.trace "Inter digit-timer expired."
|
92
|
-
complete Punchblock::Component::Input::Complete::NoMatch.new
|
93
|
-
end
|
18
|
+
def register_dtmf_event_handler
|
19
|
+
component = current_actor
|
20
|
+
call.register_handler :ami, :name => 'DTMF' do |event|
|
21
|
+
component.process_dtmf! event['Digit'] if event['End'] == 'Yes'
|
94
22
|
end
|
95
|
-
pb_logger.trace "Resetting inter-digit timer"
|
96
|
-
@inter_digit_timer.reset
|
97
|
-
end
|
98
|
-
|
99
|
-
def cancel_inter_digit_timer
|
100
|
-
return unless instance_variable_defined?(:@inter_digit_timer) && @inter_digit_timer
|
101
|
-
@inter_digit_timer.cancel
|
102
|
-
@inter_digit_timer = nil
|
103
|
-
end
|
104
|
-
|
105
|
-
def success_reason(match)
|
106
|
-
Punchblock::Component::Input::Complete::Success.new :mode => match.mode,
|
107
|
-
:confidence => match.confidence,
|
108
|
-
:utterance => match.utterance,
|
109
|
-
:interpretation => match.interpretation
|
110
23
|
end
|
111
24
|
|
112
|
-
def
|
25
|
+
def unregister_dtmf_event_handler
|
113
26
|
call.unregister_handler :ami, @dtmf_handler_id if instance_variable_defined?(:@dtmf_handler_id)
|
114
|
-
cancel_initial_timer
|
115
|
-
cancel_inter_digit_timer
|
116
|
-
send_complete_event reason
|
117
27
|
end
|
118
28
|
end
|
119
29
|
end
|