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
@@ -11,6 +11,7 @@ module Adhearsion
|
|
11
11
|
autoload :Player
|
12
12
|
|
13
13
|
PlaybackError = Class.new Adhearsion::Error # Represents failure to play audio, such as when the sound file cannot be found
|
14
|
+
NoDocError = Class.new Adhearsion::Error # Represents failure to provide documents to playback
|
14
15
|
|
15
16
|
#
|
16
17
|
# Speak output using text-to-speech (TTS)
|
@@ -18,9 +19,10 @@ module Adhearsion
|
|
18
19
|
# @param [String, #to_s] text The text to be rendered
|
19
20
|
# @param [Hash] options A set of options for output
|
20
21
|
#
|
21
|
-
# @
|
22
|
+
# @raise [PlaybackError] if the given argument could not be played
|
22
23
|
#
|
23
24
|
def say(text, options = {})
|
25
|
+
return unless text
|
24
26
|
player.play_ssml(text, options) || player.output(output_formatter.ssml_for_text(text.to_s), options)
|
25
27
|
end
|
26
28
|
alias :speak :say
|
@@ -31,9 +33,10 @@ module Adhearsion
|
|
31
33
|
# @param [String, #to_s] text The text to be rendered
|
32
34
|
# @param [Hash] options A set of options for output
|
33
35
|
#
|
34
|
-
# @
|
36
|
+
# @raise [PlaybackError] if the given argument could not be played
|
35
37
|
#
|
36
38
|
def say!(text, options = {})
|
39
|
+
return unless text
|
37
40
|
async_player.play_ssml(text, options) || async_player.output(output_formatter.ssml_for_text(text.to_s), options)
|
38
41
|
end
|
39
42
|
alias :speak! :say!
|
@@ -47,7 +50,7 @@ module Adhearsion
|
|
47
50
|
# @param [String, #to_s] characters The string of characters to be spoken
|
48
51
|
# @param [Hash] options A set of options for output
|
49
52
|
#
|
50
|
-
# @
|
53
|
+
# @raise [PlaybackError] if the given argument could not be played
|
51
54
|
#
|
52
55
|
def say_characters(characters, options = {})
|
53
56
|
player.play_ssml output_formatter.ssml_for_characters(characters), options
|
@@ -62,7 +65,7 @@ module Adhearsion
|
|
62
65
|
# @param [String, #to_s] characters The string of characters to be spoken
|
63
66
|
# @param [Hash] options A set of options for output
|
64
67
|
#
|
65
|
-
# @
|
68
|
+
# @raise [PlaybackError] if the given argument could not be played
|
66
69
|
#
|
67
70
|
def say_characters!(characters, options = {})
|
68
71
|
async_player.play_ssml output_formatter.ssml_for_characters(characters), options
|
@@ -88,12 +91,15 @@ module Adhearsion
|
|
88
91
|
# @example Play two sound files
|
89
92
|
# play "/path/to/you-sound-cute.mp3", "/path/to/what-are-you-wearing.wav"
|
90
93
|
#
|
91
|
-
# @
|
94
|
+
# @raise [PlaybackError] if (one of) the given argument(s) could not be played
|
92
95
|
#
|
93
|
-
def play(*
|
94
|
-
options = process_output_options
|
95
|
-
|
96
|
+
def play(*outputs, options)
|
97
|
+
options = process_output_options outputs, options
|
98
|
+
ssml = output_formatter.ssml_for_collection(outputs) || return
|
99
|
+
player.play_ssml ssml, options
|
96
100
|
true
|
101
|
+
rescue NoDocError
|
102
|
+
false
|
97
103
|
end
|
98
104
|
|
99
105
|
#
|
@@ -116,12 +122,15 @@ module Adhearsion
|
|
116
122
|
# @example Play two sound files
|
117
123
|
# play "/path/to/you-sound-cute.mp3", "/path/to/what-are-you-wearing.wav"
|
118
124
|
#
|
119
|
-
# @
|
120
|
-
# @
|
125
|
+
# @raise [PlaybackError] if (one of) the given argument(s) could not be played
|
126
|
+
# @return [Punchblock::Component::Output]
|
121
127
|
#
|
122
|
-
def play!(*
|
123
|
-
options = process_output_options
|
124
|
-
|
128
|
+
def play!(*outputs, options)
|
129
|
+
options = process_output_options outputs, options
|
130
|
+
ssml = output_formatter.ssml_for_collection(outputs) || return
|
131
|
+
async_player.play_ssml ssml, options
|
132
|
+
rescue NoDocError
|
133
|
+
false
|
125
134
|
end
|
126
135
|
|
127
136
|
#
|
@@ -134,7 +143,7 @@ module Adhearsion
|
|
134
143
|
# @option options [String] :fallback The text to play if the file is not available
|
135
144
|
# @option options [Symbol] :renderer The media engine to use for rendering the file
|
136
145
|
#
|
137
|
-
# @
|
146
|
+
# @raise [PlaybackError] if (one of) the given argument(s) could not be played
|
138
147
|
#
|
139
148
|
def play_audio(file, options = {})
|
140
149
|
renderer = options.delete :renderer
|
@@ -151,8 +160,8 @@ module Adhearsion
|
|
151
160
|
# @param [Hash] options Additional options to specify how exactly to say time specified.
|
152
161
|
# @option options [String] :fallback The text to play if the file is not available
|
153
162
|
#
|
154
|
-
# @
|
155
|
-
# @
|
163
|
+
# @raise [PlaybackError] if (one of) the given argument(s) could not be played
|
164
|
+
# @return [Punchblock::Component::Output]
|
156
165
|
#
|
157
166
|
def play_audio!(file, options = {})
|
158
167
|
renderer = options.delete :renderer
|
@@ -172,7 +181,7 @@ module Adhearsion
|
|
172
181
|
# @option options [String] :strftime This format is what defines the string that is sent to the Speech Synthesis Engine.
|
173
182
|
# It uses Time::strftime symbols.
|
174
183
|
#
|
175
|
-
# @
|
184
|
+
# @raise [ArgumentError] if the given argument can not be played
|
176
185
|
#
|
177
186
|
def play_time(time, options = {})
|
178
187
|
raise ArgumentError unless [Date, Time, DateTime].include?(time.class) && options.is_a?(Hash)
|
@@ -193,8 +202,8 @@ module Adhearsion
|
|
193
202
|
# @option options [String] :strftime This format is what defines the string that is sent to the Speech Synthesis Engine.
|
194
203
|
# It uses Time::strftime symbols.
|
195
204
|
#
|
196
|
-
# @
|
197
|
-
# @
|
205
|
+
# @raise [ArgumentError] if the given argument can not be played
|
206
|
+
# @return [Punchblock::Component::Output]
|
198
207
|
#
|
199
208
|
def play_time!(time, options = {})
|
200
209
|
raise ArgumentError unless [Date, Time, DateTime].include?(time.class) && options.is_a?(Hash)
|
@@ -206,9 +215,9 @@ module Adhearsion
|
|
206
215
|
# When playing numbers, Adhearsion assumes you're saying the number, not the digits. For example, play("100")
|
207
216
|
# is pronounced as "one hundred" instead of "one zero zero".
|
208
217
|
#
|
209
|
-
# @param [Numeric, String] Numeric or String containing a valid Numeric, like "321".
|
218
|
+
# @param [Numeric, String] number Numeric or String containing a valid Numeric, like "321".
|
210
219
|
#
|
211
|
-
# @
|
220
|
+
# @raise [ArgumentError] if the given argument can not be played
|
212
221
|
#
|
213
222
|
def play_numeric(number)
|
214
223
|
raise ArgumentError unless number.kind_of?(Numeric) || number =~ /^\d+$/
|
@@ -221,10 +230,10 @@ module Adhearsion
|
|
221
230
|
# When playing numbers, Adhearsion assumes you're saying the number, not the digits. For example, play("100")
|
222
231
|
# is pronounced as "one hundred" instead of "one zero zero".
|
223
232
|
#
|
224
|
-
# @param [Numeric, String] Numeric or String containing a valid Numeric, like "321".
|
233
|
+
# @param [Numeric, String] number Numeric or String containing a valid Numeric, like "321".
|
225
234
|
#
|
226
|
-
# @
|
227
|
-
# @
|
235
|
+
# @raise [ArgumentError] if the given argument can not be played
|
236
|
+
# @return [Punchblock::Component::Output]
|
228
237
|
#
|
229
238
|
def play_numeric!(number)
|
230
239
|
raise ArgumentError unless number.kind_of?(Numeric) || number =~ /^\d+$/
|
@@ -242,14 +251,14 @@ module Adhearsion
|
|
242
251
|
# input = interruptible_play ssml
|
243
252
|
# play input unless input.nil?
|
244
253
|
#
|
245
|
-
# @param [String, Numeric, Date, Time, RubySpeech::SSML::Speak, Array, Hash] The argument to play to the user, or an array of arguments.
|
246
|
-
# @param [Hash] Additional options.
|
254
|
+
# @param [String, Numeric, Date, Time, RubySpeech::SSML::Speak, Array, Hash] outputs The argument to play to the user, or an array of arguments.
|
255
|
+
# @param [Hash] options Additional options.
|
247
256
|
#
|
248
257
|
# @return [String, nil] The single DTMF character entered by the user, or nil if nothing was entered
|
249
|
-
# @
|
258
|
+
# @raise [PlaybackError] if (one of) the given argument(s) could not be played
|
250
259
|
#
|
251
|
-
def interruptible_play(*outputs)
|
252
|
-
options = process_output_options outputs
|
260
|
+
def interruptible_play(*outputs, options)
|
261
|
+
options = process_output_options outputs, options
|
253
262
|
outputs.find do |output|
|
254
263
|
digit = stream_file output, '0123456789#*', options
|
255
264
|
return digit if digit
|
@@ -259,8 +268,8 @@ module Adhearsion
|
|
259
268
|
#
|
260
269
|
# Plays a single output, not only files, accepting interruption by one of the digits specified
|
261
270
|
#
|
262
|
-
# @param [Object] String or Hash specifying output and options
|
263
|
-
# @param [String] String with the digits that are allowed to interrupt output
|
271
|
+
# @param [Object] argument String or Hash specifying output and options
|
272
|
+
# @param [String] digits String with the digits that are allowed to interrupt output
|
264
273
|
#
|
265
274
|
# @return [String, nil] The pressed digit, or nil if nothing was pressed
|
266
275
|
# @private
|
@@ -296,8 +305,13 @@ module Adhearsion
|
|
296
305
|
end
|
297
306
|
|
298
307
|
# @private
|
299
|
-
def process_output_options(
|
300
|
-
|
308
|
+
def process_output_options(outputs, options)
|
309
|
+
if options.is_a?(Hash) && outputs.count > 0
|
310
|
+
options
|
311
|
+
else
|
312
|
+
outputs << options
|
313
|
+
{}
|
314
|
+
end
|
301
315
|
end
|
302
316
|
|
303
317
|
#
|
@@ -6,14 +6,15 @@ module Adhearsion
|
|
6
6
|
class AsyncPlayer < AbstractPlayer
|
7
7
|
|
8
8
|
#
|
9
|
-
# @
|
10
|
-
# @
|
9
|
+
# @yield The output component before executing it
|
10
|
+
# @raise [PlaybackError] if (one of) the given argument(s) could not be played
|
11
11
|
#
|
12
12
|
def output(content, options = {})
|
13
13
|
options.merge! :ssml => content
|
14
14
|
component = new_output options
|
15
15
|
component.register_event_handler Punchblock::Event::Complete do |event|
|
16
16
|
controller.logger.error event if event.reason.is_a?(Punchblock::Event::Complete::Error)
|
17
|
+
throw :pass
|
17
18
|
end
|
18
19
|
controller.write_and_await_response component
|
19
20
|
component
|
@@ -8,6 +8,9 @@ module Adhearsion
|
|
8
8
|
class Formatter
|
9
9
|
|
10
10
|
def ssml_for_collection(collection)
|
11
|
+
collection = collection.compact
|
12
|
+
raise NoDocError if collection.empty?
|
13
|
+
|
11
14
|
collection.inject RubySpeech::SSML.draw do |doc, argument|
|
12
15
|
doc + case argument
|
13
16
|
when Hash
|
@@ -28,6 +31,8 @@ module Adhearsion
|
|
28
31
|
:time
|
29
32
|
when Numeric, /^\d+$/
|
30
33
|
:numeric
|
34
|
+
when /^[\d\*\#]+$/
|
35
|
+
:characters
|
31
36
|
when /^\//, ->(string) { uri? string }
|
32
37
|
:audio
|
33
38
|
else
|
@@ -45,7 +50,7 @@ module Adhearsion
|
|
45
50
|
# Generates SSML for the argument and options passed, using automatic detection
|
46
51
|
# Directly returns the argument if it is already an SSML document
|
47
52
|
#
|
48
|
-
# @param [String, Hash, RubySpeech::SSML::Speak] the argument with options as accepted by the play_ methods, or an SSML document
|
53
|
+
# @param [String, Hash, RubySpeech::SSML::Speak] args the argument with options as accepted by the play_ methods, or an SSML document
|
49
54
|
# @return [RubySpeech::SSML::Speak] an SSML document
|
50
55
|
#
|
51
56
|
def ssml_for(*args)
|
@@ -89,7 +94,7 @@ module Adhearsion
|
|
89
94
|
end
|
90
95
|
end
|
91
96
|
|
92
|
-
def ssml_for_characters(argument)
|
97
|
+
def ssml_for_characters(argument, options = {})
|
93
98
|
RubySpeech::SSML.draw do
|
94
99
|
say_as(interpret_as: 'characters') { string argument.to_s }
|
95
100
|
end
|
@@ -6,8 +6,8 @@ module Adhearsion
|
|
6
6
|
class Player < AbstractPlayer
|
7
7
|
|
8
8
|
#
|
9
|
-
# @
|
10
|
-
# @
|
9
|
+
# @yield The output component before executing it
|
10
|
+
# @raise [PlaybackError] if (one of) the given argument(s) could not be played
|
11
11
|
#
|
12
12
|
def output(content, options = {}, &block)
|
13
13
|
options.merge! :ssml => content
|
@@ -8,20 +8,21 @@ module Adhearsion
|
|
8
8
|
#
|
9
9
|
# Handle a recording
|
10
10
|
#
|
11
|
-
# @param [Adhearsion::CallController] controller on which to execute the recording
|
12
|
-
# @param [Hash] options
|
13
|
-
# @option options [Boolean, Optional] :async Execute asynchronously. Defaults to false
|
14
|
-
# @option options [Boolean, Optional] :start_beep Indicates whether subsequent record will be preceded with a beep. Default is true.
|
15
|
-
# @option options [Boolean, Optional] :start_paused Whether subsequent record will start in PAUSE mode. Default is false.
|
16
|
-
# @option options [String, Optional] :max_duration Indicates the maximum duration (seconds) for a recording.
|
17
|
-
# @option options [String, Optional] :format File format used during recording.
|
18
|
-
# @option options [String, Optional] :initial_timeout Controls how long (seconds) the recognizer should wait after the end of the prompt for the caller to speak before sending a Recorder event.
|
19
|
-
# @option options [String, Optional] :final_timeout Controls the length (seconds) of a period of silence after callers have spoken to conclude they finished.
|
20
|
-
# @option options [Boolean, Optional] :interruptible Allows the recording to be terminated by any single DTMF key, default is false
|
21
|
-
#
|
22
11
|
class Recorder
|
23
12
|
attr_accessor :record_component, :stopper_component
|
24
13
|
|
14
|
+
#
|
15
|
+
# @param [Adhearsion::CallController] controller on which to execute the recording
|
16
|
+
# @param [Hash] options
|
17
|
+
# @option options [Boolean, Optional] :async Execute asynchronously. Defaults to false
|
18
|
+
# @option options [Boolean, Optional] :start_beep Indicates whether subsequent record will be preceded with a beep. Default is true.
|
19
|
+
# @option options [Boolean, Optional] :start_paused Whether subsequent record will start in PAUSE mode. Default is false.
|
20
|
+
# @option options [String, Optional] :max_duration Indicates the maximum duration (seconds) for a recording.
|
21
|
+
# @option options [String, Optional] :format File format used during recording.
|
22
|
+
# @option options [String, Optional] :initial_timeout Controls how long (seconds) the recognizer should wait after the end of the prompt for the caller to speak before sending a Recorder event.
|
23
|
+
# @option options [String, Optional] :final_timeout Controls the length (seconds) of a period of silence after callers have spoken to conclude they finished.
|
24
|
+
# @option options [Boolean, Optional] :interruptible Allows the recording to be terminated by any single DTMF key, default is false
|
25
|
+
#
|
25
26
|
def initialize(controller, options = {})
|
26
27
|
@controller = controller
|
27
28
|
|
@@ -98,7 +99,7 @@ module Adhearsion
|
|
98
99
|
# Start a recording
|
99
100
|
#
|
100
101
|
# @example Record in a blocking way and use result
|
101
|
-
# record_result = record :start_beep => true, :max_duration =>
|
102
|
+
# record_result = record :start_beep => true, :max_duration => 60
|
102
103
|
# logger.info "Recording saved to #{record_result.complete_event.recording.uri}"
|
103
104
|
# @example Asynchronous recording, execution of the controller will continue
|
104
105
|
# record :async => true do |event|
|
@@ -106,7 +107,6 @@ module Adhearsion
|
|
106
107
|
# end
|
107
108
|
#
|
108
109
|
# @param [Hash] options
|
109
|
-
# @param [Block] block to process result of the record method, it will receive the complete Event for the method.
|
110
110
|
# @option options [Boolean, Optional] :async Execute asynchronously. Defaults to false
|
111
111
|
# @option options [Boolean, Optional] :start_beep Indicates whether subsequent record will be preceded with a beep. Default is true.
|
112
112
|
# @option options [Boolean, Optional] :start_paused Whether subsequent record will start in PAUSE mode. Default is false.
|
@@ -116,6 +116,9 @@ module Adhearsion
|
|
116
116
|
# @option options [String, Optional] :final_timeout Controls the length (seconds) of a period of silence after callers have spoken to conclude they finished.
|
117
117
|
# @option options [Boolean, String, Optional] :interruptible Allows the recording to be terminated by any single DTMF key, default is false
|
118
118
|
#
|
119
|
+
# @yield [event] Handle the recording completion event asyncronously.
|
120
|
+
# @yieldparam [Punchblock::Event::Complete] event the complete event for the recording
|
121
|
+
#
|
119
122
|
# @return Punchblock::Component::Record
|
120
123
|
#
|
121
124
|
def record(options = {})
|
@@ -8,7 +8,7 @@ module Adhearsion
|
|
8
8
|
|
9
9
|
# Utility method for DTMF GRXML grammars
|
10
10
|
#
|
11
|
-
# @param [Integer] Number of digits to accept in the grammar.
|
11
|
+
# @param [Integer] digits Number of digits to accept in the grammar.
|
12
12
|
# @return [RubySpeech::GRXML::Grammar] A grammar suitable for use in SSML prompts
|
13
13
|
#
|
14
14
|
# @private
|
@@ -27,7 +27,7 @@ module Adhearsion
|
|
27
27
|
|
28
28
|
# Utility method to create a single-digit grammar to accept only some digits
|
29
29
|
#
|
30
|
-
# @param [String] String representing the digits to accept
|
30
|
+
# @param [String] digits String representing the digits to accept
|
31
31
|
# @return [RubySpeech::GRXML::Grammar] A grammar suitable for use in SSML prompts
|
32
32
|
#
|
33
33
|
# @private
|
@@ -48,7 +48,7 @@ module Adhearsion
|
|
48
48
|
#
|
49
49
|
# Parses a DTMF tone string
|
50
50
|
#
|
51
|
-
# @param [String] the tone string to be parsed
|
51
|
+
# @param [String] dtmf the tone string to be parsed
|
52
52
|
# @return [String] the digits/*/# without any separation
|
53
53
|
#
|
54
54
|
# @private
|
data/lib/adhearsion/calls.rb
CHANGED
@@ -8,26 +8,25 @@ module Adhearsion
|
|
8
8
|
|
9
9
|
trap_exit :call_died
|
10
10
|
|
11
|
-
def from_offer(offer)
|
12
|
-
Call.new(offer).tap do |call|
|
13
|
-
self << call
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
11
|
def <<(call)
|
18
12
|
link call
|
19
13
|
self[call.id] = call
|
14
|
+
by_uri[call.uri] = call
|
20
15
|
current_actor
|
21
16
|
end
|
22
17
|
|
23
18
|
def remove_inactive_call(call)
|
24
|
-
if call_is_dead?(call)
|
19
|
+
if call_is_dead?(call)
|
25
20
|
call_id = key call
|
26
21
|
delete call_id if call_id
|
22
|
+
|
23
|
+
remove_call_uri call
|
27
24
|
elsif call.respond_to?(:id)
|
28
25
|
delete call.id
|
26
|
+
remove_call_uri call
|
29
27
|
else
|
30
|
-
delete call
|
28
|
+
call_actor = delete call
|
29
|
+
remove_call_uri call_actor
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
@@ -37,11 +36,25 @@ module Adhearsion
|
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
39
|
+
def with_uri(uri)
|
40
|
+
by_uri[uri]
|
41
|
+
end
|
42
|
+
|
40
43
|
private
|
41
44
|
|
45
|
+
def by_uri
|
46
|
+
@by_uri ||= {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def remove_call_uri(call)
|
50
|
+
uri = by_uri.key call
|
51
|
+
by_uri.delete uri if uri
|
52
|
+
end
|
53
|
+
|
42
54
|
def call_is_dead?(call)
|
43
55
|
!call.alive?
|
44
56
|
rescue NoMethodError
|
57
|
+
false
|
45
58
|
end
|
46
59
|
|
47
60
|
def call_died(call, reason)
|
@@ -16,6 +16,7 @@ module Adhearsion
|
|
16
16
|
end
|
17
17
|
|
18
18
|
desc "create /path/to/directory", "Create a new Adhearsion application under the given path"
|
19
|
+
method_option :empty, type: :boolean
|
19
20
|
def create(path)
|
20
21
|
require 'adhearsion/generators/app/app_generator'
|
21
22
|
Generators::AppGenerator.start
|
@@ -55,8 +55,8 @@ module Adhearsion
|
|
55
55
|
__
|
56
56
|
}
|
57
57
|
|
58
|
-
after_hangup_lifetime
|
59
|
-
Lifetime of a call after it has hung up
|
58
|
+
after_hangup_lifetime 1, :transform => Proc.new { |v| v.to_i }, :desc => <<-__
|
59
|
+
Lifetime of a call after it has hung up. Should be set to the minimum functional value for your application. Call actors (threads) living after hangup consume more system resources and reduce the concurrent call capacity of your application.
|
60
60
|
__
|
61
61
|
|
62
62
|
desc "Media configuration"
|
data/lib/adhearsion/console.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'pry'
|
4
|
+
require 'readline'
|
4
5
|
|
5
6
|
module Adhearsion
|
6
7
|
class Console
|
@@ -30,9 +31,9 @@ module Adhearsion
|
|
30
31
|
# Start the Adhearsion console
|
31
32
|
#
|
32
33
|
def run
|
33
|
-
set_prompt
|
34
|
-
Pry.config.command_prefix = "%"
|
35
34
|
if jruby? || cruby_with_readline?
|
35
|
+
set_prompt
|
36
|
+
Pry.config.command_prefix = "%"
|
36
37
|
logger.info "Launching Adhearsion Console"
|
37
38
|
@pry_thread = Thread.current
|
38
39
|
pry
|