adhearsion 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +29 -0
- data/Gemfile +0 -2
- data/Guardfile +2 -2
- data/README.markdown +3 -6
- data/Rakefile +1 -1
- data/adhearsion.gemspec +7 -2
- data/features/cli_create.feature +85 -7
- data/features/plugin_generator.feature +4 -0
- data/features/step_definitions/app_generator_steps.rb +8 -1
- data/lib/adhearsion.rb +6 -3
- data/lib/adhearsion/call.rb +101 -30
- data/lib/adhearsion/call_controller.rb +40 -12
- data/lib/adhearsion/call_controller/dial.rb +119 -36
- data/lib/adhearsion/call_controller/input.rb +11 -5
- data/lib/adhearsion/call_controller/output.rb +47 -33
- data/lib/adhearsion/call_controller/output/async_player.rb +3 -2
- data/lib/adhearsion/call_controller/output/formatter.rb +7 -2
- data/lib/adhearsion/call_controller/output/player.rb +2 -2
- data/lib/adhearsion/call_controller/record.rb +16 -13
- data/lib/adhearsion/call_controller/utility.rb +3 -3
- data/lib/adhearsion/calls.rb +21 -8
- data/lib/adhearsion/cli_commands/ahn_command.rb +1 -0
- data/lib/adhearsion/configuration.rb +2 -2
- data/lib/adhearsion/console.rb +3 -2
- data/lib/adhearsion/generators.rb +7 -9
- data/lib/adhearsion/generators/app/app_generator.rb +12 -2
- data/lib/adhearsion/generators/app/templates/Gemfile.erb +7 -9
- data/lib/adhearsion/generators/app/templates/README.md +0 -19
- data/lib/adhearsion/generators/app/templates/adhearsion.erb +37 -0
- data/lib/adhearsion/generators/app/templates/config/environment.rb +6 -1
- data/lib/adhearsion/generators/app/templates/events.erb +18 -0
- data/lib/adhearsion/generators/app/templates/routes.erb +19 -0
- data/lib/adhearsion/generators/app/templates/{lib/simon_game.rb → simon_game.rb} +0 -0
- data/lib/adhearsion/generators/app/templates/{spec/call_controllers/simon_game_spec.rb → simon_game_spec.rb} +0 -0
- data/lib/adhearsion/generators/controller/controller_generator.rb +2 -2
- data/lib/adhearsion/generators/controller/templates/lib/{controller.rb → controller.rb.erb} +0 -0
- data/lib/adhearsion/generators/controller/templates/spec/{controller_spec.rb → controller_spec.rb.erb} +0 -0
- data/lib/adhearsion/generators/plugin/plugin_generator.rb +16 -15
- data/lib/adhearsion/generators/plugin/templates/gitignore +17 -0
- data/lib/adhearsion/generators/plugin/templates/spec/plugin-template/controller_methods_spec.rb.tt +1 -1
- data/lib/adhearsion/initializer.rb +14 -2
- data/lib/adhearsion/logging.rb +1 -0
- data/lib/adhearsion/outbound_call.rb +3 -7
- data/lib/adhearsion/punchblock_plugin/initializer.rb +3 -2
- data/lib/adhearsion/router/openended_route.rb +1 -1
- data/lib/adhearsion/router/route.rb +4 -3
- data/lib/adhearsion/version.rb +1 -1
- data/spec/adhearsion/call_controller/dial_spec.rb +811 -79
- data/spec/adhearsion/call_controller/output/formatter_spec.rb +13 -1
- data/spec/adhearsion/call_controller/output_spec.rb +35 -1
- data/spec/adhearsion/call_controller_spec.rb +174 -18
- data/spec/adhearsion/call_spec.rb +423 -39
- data/spec/adhearsion/calls_spec.rb +19 -3
- data/spec/adhearsion/outbound_call_spec.rb +88 -45
- data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +3 -3
- data/spec/adhearsion/router/route_spec.rb +2 -2
- data/spec/spec_helper.rb +2 -0
- metadata +92 -77
- data/features/app_generator.feature +0 -49
- data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +0 -71
- data/lib/adhearsion/generators/plugin/templates/.gitignore +0 -9
@@ -64,7 +64,7 @@ module Adhearsion
|
|
64
64
|
attr_reader :block
|
65
65
|
|
66
66
|
delegate :[], :[]=, :to => :@metadata
|
67
|
-
delegate :variables, :to => :call
|
67
|
+
delegate :variables, :send_message, :to => :call
|
68
68
|
|
69
69
|
#
|
70
70
|
# Create a new instance
|
@@ -75,12 +75,13 @@ module Adhearsion
|
|
75
75
|
#
|
76
76
|
def initialize(call, metadata = nil, &block)
|
77
77
|
@call, @metadata, @block = call, metadata || {}, block
|
78
|
+
@block_context = eval "self", @block.binding if @block
|
79
|
+
@active_components = []
|
78
80
|
end
|
79
81
|
|
80
82
|
def method_missing(method_name, *args, &block)
|
81
|
-
if @
|
82
|
-
block_context
|
83
|
-
block_context.send method_name, *args, &block
|
83
|
+
if @block_context
|
84
|
+
@block_context.send method_name, *args, &block
|
84
85
|
else
|
85
86
|
super
|
86
87
|
end
|
@@ -117,7 +118,7 @@ module Adhearsion
|
|
117
118
|
call.async.register_controller self
|
118
119
|
execute_callbacks :before_call
|
119
120
|
run
|
120
|
-
rescue Call::Hangup
|
121
|
+
rescue Call::Hangup, Call::ExpiredError
|
121
122
|
logger.info "Call was hung up while executing a controller"
|
122
123
|
rescue SyntaxError, StandardError => e
|
123
124
|
Events.trigger :exception, [e, logger]
|
@@ -155,6 +156,31 @@ module Adhearsion
|
|
155
156
|
throw :pass_controller, controller_class.new(call, metadata)
|
156
157
|
end
|
157
158
|
|
159
|
+
#
|
160
|
+
# Stop execution of all the components currently running in the controller.
|
161
|
+
#
|
162
|
+
def stop_all_components
|
163
|
+
logger.info "Stopping all controller components"
|
164
|
+
@active_components.each do |component|
|
165
|
+
begin
|
166
|
+
component.stop!
|
167
|
+
rescue Punchblock::Component::InvalidActionError
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
#
|
173
|
+
# Cease execution of this controller, including any components it is executing, and pass to another.
|
174
|
+
#
|
175
|
+
# @param [Class] controller_class The class of controller to pass to
|
176
|
+
# @param [Hash] metadata generic key-value storage applicable to the controller
|
177
|
+
#
|
178
|
+
def hard_pass(controller_class, metadata = nil)
|
179
|
+
logger.info "Hard passing with active components #{@active_components.inspect}"
|
180
|
+
stop_all_components
|
181
|
+
pass controller_class, metadata
|
182
|
+
end
|
183
|
+
|
158
184
|
# @private
|
159
185
|
def execute_callbacks(type)
|
160
186
|
self.class.callbacks[type].each do |callback|
|
@@ -173,6 +199,12 @@ module Adhearsion
|
|
173
199
|
def write_and_await_response(command)
|
174
200
|
block_until_resumed
|
175
201
|
call.write_and_await_response command
|
202
|
+
if command.is_a?(Punchblock::Component::ComponentNode)
|
203
|
+
command.register_event_handler Punchblock::Event::Complete do |event|
|
204
|
+
@active_components.delete command
|
205
|
+
end
|
206
|
+
@active_components << command
|
207
|
+
end
|
176
208
|
end
|
177
209
|
|
178
210
|
# @private
|
@@ -250,13 +282,9 @@ module Adhearsion
|
|
250
282
|
def join(target, options = {})
|
251
283
|
block_until_resumed
|
252
284
|
async = (target.is_a?(Hash) ? target : options).delete :async
|
253
|
-
|
254
|
-
waiter =
|
255
|
-
|
256
|
-
call.wait_for_joined waiter
|
257
|
-
else
|
258
|
-
call.wait_for_unjoined waiter
|
259
|
-
end
|
285
|
+
join = call.join target, options
|
286
|
+
waiter = async ? join[:joined_condition] : join[:unjoined_condition]
|
287
|
+
waiter.wait
|
260
288
|
end
|
261
289
|
|
262
290
|
alias :safely :catching_standard_errors
|
@@ -36,6 +36,13 @@ module Adhearsion
|
|
36
36
|
# @option options [CallController] :confirm the controller to execute on the first outbound call to be answered, to give an opportunity to screen the call. The calls will be joined if the outbound call is still active after this controller completes.
|
37
37
|
# @option options [Hash] :confirm_metadata Metadata to set on the confirmation controller before executing it. This is shared between all calls if dialing multiple endpoints; if you care about it being mutated, you should provide an immutable value (using eg https://github.com/harukizaemon/hamster).
|
38
38
|
#
|
39
|
+
# @option options [Hash] :join_options Options to specify the kind of join operation to perform. See `Call#join` for details.
|
40
|
+
# @option options [Call, String, Hash] :join_target the target to join to. May be a Call object, a call ID (String, Hash) or a mixer name (Hash). See `Call#join` for details.
|
41
|
+
#
|
42
|
+
# @option options [#call] :pre_join A callback to be executed immediately prior to answering and joining a successful call. Is called with a single parameter which is the outbound call being joined.
|
43
|
+
#
|
44
|
+
# @option options [Array, #call] :ringback A collection of audio (see #play for acceptable values) to render as a replacement for ringback. If a callback is passed, it will be used to start ringback, and must return something that responds to #stop! to stop it.
|
45
|
+
#
|
39
46
|
# @example Make a call to the PSTN using my SIP provider for VoIP termination
|
40
47
|
# dial "SIP/19095551001@my.sip.voip.terminator.us"
|
41
48
|
#
|
@@ -49,10 +56,13 @@ module Adhearsion
|
|
49
56
|
#
|
50
57
|
def dial(to, options = {})
|
51
58
|
dial = Dial.new to, options, call
|
52
|
-
dial.run
|
59
|
+
dial.run(self)
|
53
60
|
dial.await_completion
|
61
|
+
dial.terminate_ringback
|
54
62
|
dial.cleanup_calls
|
55
63
|
dial.status
|
64
|
+
ensure
|
65
|
+
catching_standard_errors { dial.delete_logger if dial }
|
56
66
|
end
|
57
67
|
|
58
68
|
# Dial one or more third parties and join one to this call after execution of a confirmation controller.
|
@@ -63,10 +73,13 @@ module Adhearsion
|
|
63
73
|
# @see #dial
|
64
74
|
def dial_and_confirm(to, options = {})
|
65
75
|
dial = ParallelConfirmationDial.new to, options, call
|
66
|
-
dial.run
|
76
|
+
dial.run(self)
|
67
77
|
dial.await_completion
|
78
|
+
dial.terminate_ringback
|
68
79
|
dial.cleanup_calls
|
69
80
|
dial.status
|
81
|
+
ensure
|
82
|
+
catching_standard_errors { dial.delete_logger if dial }
|
70
83
|
end
|
71
84
|
|
72
85
|
class Dial
|
@@ -74,6 +87,7 @@ module Adhearsion
|
|
74
87
|
|
75
88
|
def initialize(to, options, call)
|
76
89
|
raise Call::Hangup unless call.alive? && call.active?
|
90
|
+
@id = SecureRandom.uuid
|
77
91
|
@options, @call = options, call
|
78
92
|
@targets = to.respond_to?(:has_key?) ? to : Array(to)
|
79
93
|
@call_targets = {}
|
@@ -81,12 +95,13 @@ module Adhearsion
|
|
81
95
|
end
|
82
96
|
|
83
97
|
def inspect
|
84
|
-
"#<#{self.class} to=#{@to.inspect} options=#{@options.inspect}>"
|
98
|
+
"#<#{self.class}[#{@id}] to=#{@to.inspect} options=#{@options.inspect}>"
|
85
99
|
end
|
86
100
|
|
87
101
|
# Prep outbound calls, link call lifecycles and place outbound calls
|
88
|
-
def run
|
102
|
+
def run(controller)
|
89
103
|
track_originating_call
|
104
|
+
start_ringback controller
|
90
105
|
prep_calls
|
91
106
|
place_calls
|
92
107
|
end
|
@@ -102,19 +117,42 @@ module Adhearsion
|
|
102
117
|
end
|
103
118
|
end
|
104
119
|
|
120
|
+
#
|
121
|
+
# Starts ringback on the specified controller
|
122
|
+
#
|
123
|
+
# @param [Adhearsion::CallController] controller the controller on which to play ringback
|
124
|
+
def start_ringback(controller)
|
125
|
+
return unless @ringback
|
126
|
+
@ringback_component = if @ringback.respond_to?(:call)
|
127
|
+
@ringback.call
|
128
|
+
else
|
129
|
+
controller.play! @ringback, repeat_times: 0
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Terminates any ringback that might be playing
|
135
|
+
#
|
136
|
+
def terminate_ringback
|
137
|
+
return unless @ringback_component
|
138
|
+
return unless @ringback_component.executing?
|
139
|
+
@ringback_component.stop!
|
140
|
+
end
|
141
|
+
|
105
142
|
#
|
106
143
|
# Prepares a set of OutboundCall actors to be dialed and links their lifecycles to the Dial operation
|
107
144
|
#
|
108
145
|
# @yield Each call to the passed block for further setup operations
|
109
146
|
def prep_calls
|
110
|
-
@calls =
|
147
|
+
@calls = Set.new
|
148
|
+
@targets.map do |target, specific_options|
|
111
149
|
new_call = OutboundCall.new
|
112
150
|
|
113
151
|
join_status = JoinStatus.new
|
114
152
|
status.joins[new_call] = join_status
|
115
153
|
|
116
154
|
new_call.on_end do |event|
|
117
|
-
@latch.countdown! unless new_call["dial_countdown_#{@
|
155
|
+
@latch.countdown! unless new_call["dial_countdown_#{@id}"]
|
118
156
|
if event.reason == :error
|
119
157
|
status.error!
|
120
158
|
join_status.errored!
|
@@ -127,7 +165,7 @@ module Adhearsion
|
|
127
165
|
new_call.on_unjoined @call do |unjoined|
|
128
166
|
join_status.ended
|
129
167
|
unless @splitting
|
130
|
-
new_call["dial_countdown_#{@
|
168
|
+
new_call["dial_countdown_#{@id}"] = true
|
131
169
|
@latch.countdown!
|
132
170
|
end
|
133
171
|
end
|
@@ -145,7 +183,10 @@ module Adhearsion
|
|
145
183
|
pre_join_tasks new_call
|
146
184
|
@call.answer
|
147
185
|
join_status.started
|
148
|
-
new_call.join @
|
186
|
+
new_call.join @join_target, @join_options
|
187
|
+
unless @join_target == @call
|
188
|
+
@call.join @join_target, @join_options
|
189
|
+
end
|
149
190
|
status.answer!
|
150
191
|
elsif status.result == :answer
|
151
192
|
join_status.lost_confirmation!
|
@@ -156,7 +197,7 @@ module Adhearsion
|
|
156
197
|
|
157
198
|
yield new_call if block_given?
|
158
199
|
|
159
|
-
new_call
|
200
|
+
@calls << new_call
|
160
201
|
end
|
161
202
|
|
162
203
|
status.calls = @calls
|
@@ -183,29 +224,49 @@ module Adhearsion
|
|
183
224
|
def split(targets = {})
|
184
225
|
logger.info "Splitting calls apart"
|
185
226
|
@splitting = true
|
186
|
-
@calls.
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
227
|
+
calls_to_split = @calls.map do |call|
|
228
|
+
ignoring_ended_calls do
|
229
|
+
[call.id, call] if call.active?
|
230
|
+
end
|
231
|
+
end.compact
|
232
|
+
logger.info "Splitting peer calls #{calls_to_split.map(&:first).join ", "}"
|
233
|
+
calls_to_split.each do |id, call|
|
234
|
+
ignoring_ended_calls do
|
235
|
+
logger.info "Unjoining peer #{call.id} from #{join_target}"
|
236
|
+
ignoring_missing_joins { call.unjoin join_target }
|
237
|
+
if split_controller = targets[:others]
|
238
|
+
logger.info "Executing split controller #{split_controller} on #{call.id}"
|
239
|
+
call.execute_controller split_controller.new(call, 'current_dial' => self), targets[:others_callback]
|
240
|
+
end
|
192
241
|
end
|
193
242
|
end
|
194
|
-
|
195
|
-
|
196
|
-
|
243
|
+
ignoring_ended_calls do
|
244
|
+
if join_target != @call
|
245
|
+
logger.info "Unjoining main call #{@call.id} from #{join_target}"
|
246
|
+
@call.unjoin join_target
|
247
|
+
end
|
248
|
+
if split_controller = targets[:main]
|
249
|
+
logger.info "Executing split controller #{split_controller} on main call"
|
250
|
+
@call.execute_controller split_controller.new(@call, 'current_dial' => self), targets[:main_callback]
|
251
|
+
end
|
197
252
|
end
|
198
253
|
end
|
199
254
|
|
200
255
|
# Rejoin parties that were previously split
|
201
256
|
# @param [Call, String, Hash] target The target to join calls to. See Call#join for details.
|
202
|
-
|
257
|
+
# @param [Hash] join_options Options to specify the kind of join operation to perform. See `Call#join` for details.
|
258
|
+
def rejoin(target = nil, join_options = nil)
|
259
|
+
target ||= join_target
|
260
|
+
join_options ||= @join_options
|
203
261
|
logger.info "Rejoining to #{target}"
|
204
|
-
|
205
|
-
@call
|
262
|
+
ignoring_ended_calls do
|
263
|
+
unless target == @call
|
264
|
+
@join_target = target
|
265
|
+
@call.join target, join_options
|
266
|
+
end
|
206
267
|
end
|
207
268
|
@calls.each do |call|
|
208
|
-
call.join target
|
269
|
+
ignoring_ended_calls { call.join target, join_options }
|
209
270
|
end
|
210
271
|
end
|
211
272
|
|
@@ -213,16 +274,15 @@ module Adhearsion
|
|
213
274
|
# @param [Dial] other the other dial operation to merge calls from
|
214
275
|
def merge(other)
|
215
276
|
logger.info "Merging with #{other.inspect}"
|
216
|
-
mixer_name = SecureRandom.uuid
|
217
277
|
|
218
278
|
split
|
219
279
|
other.split
|
220
280
|
|
221
|
-
rejoin
|
222
|
-
other.rejoin
|
281
|
+
rejoin({mixer_name: @id}, {})
|
282
|
+
other.rejoin({mixer_name: @id}, {})
|
223
283
|
|
224
284
|
calls_to_merge = other.status.calls + [other.root_call]
|
225
|
-
@calls.
|
285
|
+
@calls.merge calls_to_merge
|
226
286
|
|
227
287
|
latch = CountDownLatch.new calls_to_merge.size
|
228
288
|
calls_to_merge.each do |call|
|
@@ -236,7 +296,9 @@ module Adhearsion
|
|
236
296
|
def await_completion
|
237
297
|
@latch.wait(@options[:timeout]) || status.timeout!
|
238
298
|
return unless status.result == :answer
|
299
|
+
logger.debug "Main calls were completed, waiting for any added calls: #{@waiters.inspect}"
|
239
300
|
@waiters.each(&:wait)
|
301
|
+
logger.debug "All calls were completed, unblocking."
|
240
302
|
end
|
241
303
|
|
242
304
|
#
|
@@ -249,9 +311,8 @@ module Adhearsion
|
|
249
311
|
# Hangup any remaining calls
|
250
312
|
def cleanup_calls
|
251
313
|
calls_to_hangup = @calls.map do |call|
|
252
|
-
|
314
|
+
ignoring_ended_calls do
|
253
315
|
[call.id, call] if call.active?
|
254
|
-
rescue Celluloid::DeadActorError
|
255
316
|
end
|
256
317
|
end.compact
|
257
318
|
if calls_to_hangup.size.zero?
|
@@ -263,15 +324,15 @@ module Adhearsion
|
|
263
324
|
else
|
264
325
|
logger.info "#dial finished. Hanging up #{calls_to_hangup.size} outbound calls which are still active: #{calls_to_hangup.map(&:first).join ", "}."
|
265
326
|
calls_to_hangup.each do |id, outbound_call|
|
266
|
-
|
267
|
-
outbound_call.hangup
|
268
|
-
rescue Celluloid::DeadActorError
|
269
|
-
# This actor may previously have been shut down due to the call ending
|
270
|
-
end
|
327
|
+
ignoring_ended_calls { outbound_call.hangup }
|
271
328
|
end
|
272
329
|
end
|
273
330
|
end
|
274
331
|
|
332
|
+
def delete_logger
|
333
|
+
::Logging::Repository.instance.delete logger_id
|
334
|
+
end
|
335
|
+
|
275
336
|
protected
|
276
337
|
|
277
338
|
def root_call
|
@@ -280,6 +341,15 @@ module Adhearsion
|
|
280
341
|
|
281
342
|
private
|
282
343
|
|
344
|
+
# @private
|
345
|
+
def logger_id
|
346
|
+
"#{self.class}: #{@id}"
|
347
|
+
end
|
348
|
+
|
349
|
+
def join_target
|
350
|
+
@join_target || @call
|
351
|
+
end
|
352
|
+
|
283
353
|
def set_defaults
|
284
354
|
@status = DialStatus.new
|
285
355
|
|
@@ -294,6 +364,12 @@ module Adhearsion
|
|
294
364
|
@confirmation_controller = @options.delete :confirm
|
295
365
|
@confirmation_metadata = @options.delete :confirm_metadata
|
296
366
|
|
367
|
+
@pre_join = @options.delete :pre_join
|
368
|
+
@ringback = @options.delete :ringback
|
369
|
+
|
370
|
+
@join_options = @options.delete(:join_options) || {}
|
371
|
+
@join_target = @options.delete(:join_target) || @call
|
372
|
+
|
297
373
|
@skip_cleanup = false
|
298
374
|
end
|
299
375
|
|
@@ -305,15 +381,15 @@ module Adhearsion
|
|
305
381
|
end
|
306
382
|
|
307
383
|
def pre_join_tasks(call)
|
384
|
+
@pre_join[call] if @pre_join
|
385
|
+
terminate_ringback
|
308
386
|
end
|
309
387
|
|
310
388
|
def on_all_except(call)
|
311
389
|
@calls.each do |target_call|
|
312
|
-
|
390
|
+
ignoring_ended_calls do
|
313
391
|
next if target_call.id == call.id
|
314
392
|
yield target_call
|
315
|
-
rescue Celluloid::DeadActorError
|
316
|
-
# This actor may previously have been shut down due to the call ending
|
317
393
|
end
|
318
394
|
end
|
319
395
|
end
|
@@ -323,6 +399,12 @@ module Adhearsion
|
|
323
399
|
rescue Punchblock::ProtocolError => e
|
324
400
|
raise unless e.name == :service_unavailable
|
325
401
|
end
|
402
|
+
|
403
|
+
def ignoring_ended_calls
|
404
|
+
yield
|
405
|
+
rescue Celluloid::DeadActorError, Adhearsion::Call::Hangup, Adhearsion::Call::ExpiredError
|
406
|
+
# This actor may previously have been shut down due to the call ending
|
407
|
+
end
|
326
408
|
end
|
327
409
|
|
328
410
|
class ParallelConfirmationDial < Dial
|
@@ -337,6 +419,7 @@ module Adhearsion
|
|
337
419
|
end
|
338
420
|
|
339
421
|
def pre_join_tasks(call)
|
422
|
+
super
|
340
423
|
on_all_except call do |target_call|
|
341
424
|
if @apology_controller
|
342
425
|
logger.info "#dial apologising to call #{target_call.id} because this call has been confirmed by another channel"
|
@@ -40,10 +40,13 @@ module Adhearsion
|
|
40
40
|
# @see Output#play
|
41
41
|
# @see CallController#pass
|
42
42
|
#
|
43
|
-
def ask(*args, &block)
|
43
|
+
def ask(*args, options, &block)
|
44
44
|
logger.warn "This implementation of #ask is deprecated due to issues with dropped DTMF. For a solution, see http://adhearsion.com/docs/common_problems#toc_3"
|
45
45
|
|
46
|
-
options
|
46
|
+
unless options.is_a?(Hash)
|
47
|
+
args << options
|
48
|
+
options = {}
|
49
|
+
end
|
47
50
|
sound_files = args.flatten
|
48
51
|
|
49
52
|
menu_instance = MenuDSL::Menu.new options do
|
@@ -130,10 +133,13 @@ module Adhearsion
|
|
130
133
|
# @see Output#play
|
131
134
|
# @see CallController#pass
|
132
135
|
#
|
133
|
-
def menu(*args, &block)
|
136
|
+
def menu(*args, options, &block)
|
134
137
|
logger.warn "This implementation of #menu is deprecated due to issues with dropped DTMF. For a solution, see http://adhearsion.com/docs/common_problems#toc_3"
|
135
138
|
|
136
|
-
options
|
139
|
+
unless options.is_a?(Hash)
|
140
|
+
args << options
|
141
|
+
options = {}
|
142
|
+
end
|
137
143
|
sound_files = args.flatten
|
138
144
|
|
139
145
|
menu_instance = MenuDSL::Menu.new options, &block
|
@@ -203,7 +209,7 @@ module Adhearsion
|
|
203
209
|
#
|
204
210
|
# Waits for a single digit and returns it, or returns nil if nothing was pressed
|
205
211
|
#
|
206
|
-
# @param [Integer] the timeout to wait before returning, in seconds. nil or -1 mean no timeout.
|
212
|
+
# @param [Integer] timeout the timeout to wait before returning, in seconds. nil or -1 mean no timeout.
|
207
213
|
# @return [String, nil] the pressed key, or nil if timeout was reached.
|
208
214
|
#
|
209
215
|
# @private
|