adhearsion 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -3
  3. data/CHANGELOG.md +29 -0
  4. data/Gemfile +0 -2
  5. data/Guardfile +2 -2
  6. data/README.markdown +3 -6
  7. data/Rakefile +1 -1
  8. data/adhearsion.gemspec +7 -2
  9. data/features/cli_create.feature +85 -7
  10. data/features/plugin_generator.feature +4 -0
  11. data/features/step_definitions/app_generator_steps.rb +8 -1
  12. data/lib/adhearsion.rb +6 -3
  13. data/lib/adhearsion/call.rb +101 -30
  14. data/lib/adhearsion/call_controller.rb +40 -12
  15. data/lib/adhearsion/call_controller/dial.rb +119 -36
  16. data/lib/adhearsion/call_controller/input.rb +11 -5
  17. data/lib/adhearsion/call_controller/output.rb +47 -33
  18. data/lib/adhearsion/call_controller/output/async_player.rb +3 -2
  19. data/lib/adhearsion/call_controller/output/formatter.rb +7 -2
  20. data/lib/adhearsion/call_controller/output/player.rb +2 -2
  21. data/lib/adhearsion/call_controller/record.rb +16 -13
  22. data/lib/adhearsion/call_controller/utility.rb +3 -3
  23. data/lib/adhearsion/calls.rb +21 -8
  24. data/lib/adhearsion/cli_commands/ahn_command.rb +1 -0
  25. data/lib/adhearsion/configuration.rb +2 -2
  26. data/lib/adhearsion/console.rb +3 -2
  27. data/lib/adhearsion/generators.rb +7 -9
  28. data/lib/adhearsion/generators/app/app_generator.rb +12 -2
  29. data/lib/adhearsion/generators/app/templates/Gemfile.erb +7 -9
  30. data/lib/adhearsion/generators/app/templates/README.md +0 -19
  31. data/lib/adhearsion/generators/app/templates/adhearsion.erb +37 -0
  32. data/lib/adhearsion/generators/app/templates/config/environment.rb +6 -1
  33. data/lib/adhearsion/generators/app/templates/events.erb +18 -0
  34. data/lib/adhearsion/generators/app/templates/routes.erb +19 -0
  35. data/lib/adhearsion/generators/app/templates/{lib/simon_game.rb → simon_game.rb} +0 -0
  36. data/lib/adhearsion/generators/app/templates/{spec/call_controllers/simon_game_spec.rb → simon_game_spec.rb} +0 -0
  37. data/lib/adhearsion/generators/controller/controller_generator.rb +2 -2
  38. data/lib/adhearsion/generators/controller/templates/lib/{controller.rb → controller.rb.erb} +0 -0
  39. data/lib/adhearsion/generators/controller/templates/spec/{controller_spec.rb → controller_spec.rb.erb} +0 -0
  40. data/lib/adhearsion/generators/plugin/plugin_generator.rb +16 -15
  41. data/lib/adhearsion/generators/plugin/templates/gitignore +17 -0
  42. data/lib/adhearsion/generators/plugin/templates/spec/plugin-template/controller_methods_spec.rb.tt +1 -1
  43. data/lib/adhearsion/initializer.rb +14 -2
  44. data/lib/adhearsion/logging.rb +1 -0
  45. data/lib/adhearsion/outbound_call.rb +3 -7
  46. data/lib/adhearsion/punchblock_plugin/initializer.rb +3 -2
  47. data/lib/adhearsion/router/openended_route.rb +1 -1
  48. data/lib/adhearsion/router/route.rb +4 -3
  49. data/lib/adhearsion/version.rb +1 -1
  50. data/spec/adhearsion/call_controller/dial_spec.rb +811 -79
  51. data/spec/adhearsion/call_controller/output/formatter_spec.rb +13 -1
  52. data/spec/adhearsion/call_controller/output_spec.rb +35 -1
  53. data/spec/adhearsion/call_controller_spec.rb +174 -18
  54. data/spec/adhearsion/call_spec.rb +423 -39
  55. data/spec/adhearsion/calls_spec.rb +19 -3
  56. data/spec/adhearsion/outbound_call_spec.rb +88 -45
  57. data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +3 -3
  58. data/spec/adhearsion/router/route_spec.rb +2 -2
  59. data/spec/spec_helper.rb +2 -0
  60. metadata +92 -77
  61. data/features/app_generator.feature +0 -49
  62. data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +0 -71
  63. 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
- # @raises [PlaybackError] if the given argument could not be played
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
- # @raises [PlaybackError] if the given argument could not be played
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
- # @raises [PlaybackError] if the given argument could not be played
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
- # @raises [PlaybackError] if the given argument could not be played
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
- # @raises [PlaybackError] if (one of) the given argument(s) could not be played
94
+ # @raise [PlaybackError] if (one of) the given argument(s) could not be played
92
95
  #
93
- def play(*arguments)
94
- options = process_output_options arguments
95
- player.play_ssml output_formatter.ssml_for_collection(arguments), options
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
- # @raises [PlaybackError] if (one of) the given argument(s) could not be played
120
- # @returns [Punchblock::Component::Output]
125
+ # @raise [PlaybackError] if (one of) the given argument(s) could not be played
126
+ # @return [Punchblock::Component::Output]
121
127
  #
122
- def play!(*arguments)
123
- options = process_output_options arguments
124
- async_player.play_ssml output_formatter.ssml_for_collection(arguments), options
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
- # @raises [PlaybackError] if (one of) the given argument(s) could not be played
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
- # @raises [PlaybackError] if (one of) the given argument(s) could not be played
155
- # @returns [Punchblock::Component::Output]
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
- # @raises [ArgumentError] if the given argument can not be played
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
- # @raises [ArgumentError] if the given argument can not be played
197
- # @returns [Punchblock::Component::Output]
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
- # @raises [ArgumentError] if the given argument can not be played
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
- # @raises [ArgumentError] if the given argument can not be played
227
- # @returns [Punchblock::Component::Output]
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
- # @raises [PlaybackError] if (one of) the given argument(s) could not be played
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(arguments)
300
- arguments.last.is_a?(Hash) && arguments.count > 1 ? arguments.pop : {}
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
- # @yields The output component before executing it
10
- # @raises [PlaybackError] if (one of) the given argument(s) could not be played
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
- # @yields The output component before executing it
10
- # @raises [PlaybackError] if (one of) the given argument(s) could not be played
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 => 60_000
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
@@ -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) != nil
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 30, :transform => Proc.new { |v| v.to_i }, :desc => <<-__
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"
@@ -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