jicksta-adhearsion 0.7.999

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.
Files changed (107) hide show
  1. data/CHANGELOG +6 -0
  2. data/EVENTS +11 -0
  3. data/LICENSE +456 -0
  4. data/README.txt +5 -0
  5. data/Rakefile +120 -0
  6. data/adhearsion.gemspec +146 -0
  7. data/app_generators/ahn/USAGE +5 -0
  8. data/app_generators/ahn/ahn_generator.rb +87 -0
  9. data/app_generators/ahn/templates/.ahnrc +34 -0
  10. data/app_generators/ahn/templates/README +8 -0
  11. data/app_generators/ahn/templates/Rakefile +23 -0
  12. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
  13. data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
  14. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
  15. data/app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml +12 -0
  16. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
  17. data/app_generators/ahn/templates/components/restful_rpc/README.markdown +11 -0
  18. data/app_generators/ahn/templates/components/restful_rpc/config.yml +34 -0
  19. data/app_generators/ahn/templates/components/restful_rpc/example-client.rb +48 -0
  20. data/app_generators/ahn/templates/components/restful_rpc/restful_rpc.rb +87 -0
  21. data/app_generators/ahn/templates/components/simon_game/simon_game.rb +56 -0
  22. data/app_generators/ahn/templates/config/startup.rb +53 -0
  23. data/app_generators/ahn/templates/dialplan.rb +3 -0
  24. data/app_generators/ahn/templates/events.rb +32 -0
  25. data/bin/ahn +28 -0
  26. data/bin/ahnctl +68 -0
  27. data/bin/jahn +42 -0
  28. data/examples/asterisk_manager_interface/standalone.rb +51 -0
  29. data/lib/adhearsion/cli.rb +223 -0
  30. data/lib/adhearsion/component_manager/spec_framework.rb +24 -0
  31. data/lib/adhearsion/component_manager.rb +208 -0
  32. data/lib/adhearsion/events_support.rb +84 -0
  33. data/lib/adhearsion/foundation/all.rb +9 -0
  34. data/lib/adhearsion/foundation/blank_slate.rb +5 -0
  35. data/lib/adhearsion/foundation/custom_daemonizer.rb +45 -0
  36. data/lib/adhearsion/foundation/event_socket.rb +203 -0
  37. data/lib/adhearsion/foundation/future_resource.rb +36 -0
  38. data/lib/adhearsion/foundation/global.rb +1 -0
  39. data/lib/adhearsion/foundation/metaprogramming.rb +17 -0
  40. data/lib/adhearsion/foundation/numeric.rb +13 -0
  41. data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
  42. data/lib/adhearsion/foundation/relationship_properties.rb +42 -0
  43. data/lib/adhearsion/foundation/string.rb +26 -0
  44. data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
  45. data/lib/adhearsion/foundation/thread_safety.rb +7 -0
  46. data/lib/adhearsion/host_definitions.rb +67 -0
  47. data/lib/adhearsion/initializer/asterisk.rb +81 -0
  48. data/lib/adhearsion/initializer/configuration.rb +254 -0
  49. data/lib/adhearsion/initializer/database.rb +49 -0
  50. data/lib/adhearsion/initializer/drb.rb +31 -0
  51. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  52. data/lib/adhearsion/initializer/rails.rb +40 -0
  53. data/lib/adhearsion/initializer.rb +373 -0
  54. data/lib/adhearsion/logging.rb +92 -0
  55. data/lib/adhearsion/tasks/database.rb +5 -0
  56. data/lib/adhearsion/tasks/deprecations.rb +59 -0
  57. data/lib/adhearsion/tasks/generating.rb +20 -0
  58. data/lib/adhearsion/tasks/lint.rb +4 -0
  59. data/lib/adhearsion/tasks/testing.rb +37 -0
  60. data/lib/adhearsion/tasks.rb +16 -0
  61. data/lib/adhearsion/version.rb +9 -0
  62. data/lib/adhearsion/voip/asterisk/agi_server.rb +81 -0
  63. data/lib/adhearsion/voip/asterisk/commands.rb +1284 -0
  64. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  65. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  66. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  67. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  68. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  69. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1754 -0
  70. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +286 -0
  71. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
  72. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
  73. data/lib/adhearsion/voip/asterisk/manager_interface.rb +562 -0
  74. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  75. data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
  76. data/lib/adhearsion/voip/asterisk.rb +4 -0
  77. data/lib/adhearsion/voip/call.rb +440 -0
  78. data/lib/adhearsion/voip/call_routing.rb +64 -0
  79. data/lib/adhearsion/voip/commands.rb +9 -0
  80. data/lib/adhearsion/voip/constants.rb +39 -0
  81. data/lib/adhearsion/voip/conveniences.rb +18 -0
  82. data/lib/adhearsion/voip/dial_plan.rb +218 -0
  83. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  84. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  85. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  86. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  87. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +71 -0
  88. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  89. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  90. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  91. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  92. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  93. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  94. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  95. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  96. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  97. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  98. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  99. data/lib/adhearsion.rb +37 -0
  100. data/lib/theatre/README.markdown +64 -0
  101. data/lib/theatre/callback_definition_loader.rb +84 -0
  102. data/lib/theatre/guid.rb +23 -0
  103. data/lib/theatre/invocation.rb +121 -0
  104. data/lib/theatre/namespace_manager.rb +153 -0
  105. data/lib/theatre/version.rb +2 -0
  106. data/lib/theatre.rb +151 -0
  107. metadata +177 -0
@@ -0,0 +1,140 @@
1
+ require File.join(File.dirname(__FILE__), 'config_generator')
2
+
3
+ module Adhearsion
4
+ module VoIP
5
+ module Asterisk
6
+ module ConfigFileGenerators
7
+ class Agents < AsteriskConfigGenerator
8
+
9
+ attr_accessor :general_section, :agent_section, :agent_definitions, :agent_section_special
10
+ def initialize
11
+ @general_section = {}
12
+ @agent_section = {}
13
+ @agent_section_special = {} # Uses => separator
14
+ @agent_definitions = []
15
+
16
+ super
17
+ end
18
+
19
+ def to_s
20
+ AsteriskConfigGenerator.warning_message +
21
+ general_section.inject("[general]") { |section,(key,value)| section + "\n#{key}=#{value}" } +
22
+ agent_section.inject("\n[agents]") { |section,(key,value)| section + "\n#{key}=#{value}" } +
23
+ agent_section_special.inject("") { |section,(key,value)| section + "\n#{key} => #{value}" } +
24
+ agent_definitions.inject("\n") do |section,properties|
25
+ section + "\nagent => #{properties[:id]},#{properties[:password]},#{properties[:name]}"
26
+ end
27
+ end
28
+ alias conf to_s # Allows "agents.conf" if agents.kind_of?(Agents)
29
+
30
+ def agent(id, properties)
31
+ agent_definitions << {:id => id}.merge(properties)
32
+ end
33
+
34
+ # Group memberships for agents (may change in mid-file)
35
+ # WHAT DOES GROUPING ACCOMPLISH?
36
+ def groups(*args)
37
+ agent_section[:group] = args.join(",")
38
+ end
39
+
40
+ # Define whether callbacklogins should be stored in astdb for
41
+ # persistence. Persistent logins will be reloaded after
42
+ # Asterisk restarts.
43
+ def persistent_agents(yes_or_no)
44
+ general_section[:persistentagents] = boolean_to_yes_no yes_or_no
45
+ end
46
+
47
+ # enable or disable a single extension from longing in as multiple
48
+ # agents, defaults to enabled
49
+ def allow_multiple_logins_per_extension(yes_or_no)
50
+ general_section[:multiplelogin] = boolean_to_yes_no yes_or_no
51
+ end
52
+
53
+ # Define maxlogintries to allow agent to try max logins before
54
+ # failed. Default to 3
55
+ def max_login_tries(number_of_tries)
56
+ agent_section[:maxlogintries] = number_of_tries
57
+ end
58
+
59
+ # Define autologoff times if appropriate. This is how long
60
+ # the phone has to ring with no answer before the agent is
61
+ # automatically logged off (in seconds)
62
+ def log_off_after_duration(time_in_seconds)
63
+ agent_section[:autologoff] = time_in_seconds
64
+ end
65
+
66
+ # Define autologoffunavail to have agents automatically logged
67
+ # out when the extension that they are at returns a CHANUNAVAIL
68
+ # status when a call is attempted to be sent there.
69
+ # Default is "no".
70
+ def log_off_if_unavailable(yes_or_no)
71
+ agent_section[:autologoffunavail] = boolean_to_yes_no yes_or_no
72
+ end
73
+
74
+ # Define ackcall to require an acknowledgement by '#' when
75
+ # an agent logs in using agentcallbacklogin. Default is "no".
76
+ def require_hash_to_acknowledge(yes_or_no)
77
+ agent_section[:ackcall] = boolean_to_yes_no yes_or_no
78
+ end
79
+
80
+ # Define endcall to allow an agent to hangup a call by '*'.
81
+ # Default is "yes". Set this to "no" to ignore '*'.
82
+ def allow_star_to_hangup(yes_or_no)
83
+ agent_section[:endcall] = boolean_to_yes_no yes_or_no
84
+ end
85
+
86
+ # Define wrapuptime. This is the minimum amount of time when
87
+ # after disconnecting before the caller can receive a new call
88
+ # note this is in milliseconds.
89
+ def time_between_calls(time_in_seconds)
90
+ agent_section[:wrapuptime] = (time_in_seconds * 1000).to_i
91
+ end
92
+
93
+ # Define the default musiconhold for agents
94
+ # musiconhold => music_class
95
+ def hold_music_class(music_class)
96
+ agent_section_special[:musiconhold] = music_class.to_s
97
+ end
98
+
99
+ # TODO: I'm not exactly sure what this even does....
100
+
101
+ # Define the default good bye sound file for agents
102
+ # default to vm-goodbye
103
+ def play_on_agent_goodbye(sound_file_name)
104
+ agent_section_special[:agentgoodbye] = sound_file_name
105
+ end
106
+
107
+ # Define updatecdr. This is whether or not to change the source
108
+ # channel in the CDR record for this call to agent/agent_id so
109
+ # that we know which agent generates the call
110
+ def change_cdr_source(yes_or_no)
111
+ agent_section[:updatecdr] = boolean_to_yes_no yes_or_no
112
+ end
113
+
114
+ # An optional custom beep sound file to play to always-connected agents.
115
+ def play_for_waiting_keep_alive(sound_file)
116
+ agent_section[:custom_beep] = sound_file
117
+ end
118
+
119
+ def record_agent_calls(yes_or_no)
120
+ agent_section[:recordagentcalls] = boolean_to_yes_no yes_or_no
121
+ end
122
+
123
+ def recording_format(symbol)
124
+ raise ArgumentError, "Unrecognized format #{symbol}" unless [:wav, :wav49, :gsm].include? symbol
125
+ agent_section[:recordformat] = symbol
126
+ end
127
+
128
+ def recording_prefix(string)
129
+ agent_section[:urlprefix] = string
130
+ end
131
+
132
+ def save_recordings_in(path_to_directory)
133
+ agent_section[:savecallsin] = path_to_directory
134
+ end
135
+
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,101 @@
1
+ module Adhearsion
2
+ module VoIP
3
+ module Asterisk
4
+ module ConfigFileGenerators
5
+ class AsteriskConfigGenerator
6
+
7
+ SECTION_TITLE = /(\[[\w_-]+\])/
8
+
9
+ class << self
10
+
11
+ # Converts a config file into a Hash of contexts mapping to two dimensional array of pairs
12
+ def create_sanitary_hash_from(config_file_content)
13
+ almost_sanitized = Hash[*config_file_content.
14
+ grep(/^\s*[^;\s]/). # Grep lines that aren't commented out
15
+ join. # Convert them into one String again
16
+ split(SECTION_TITLE). # Separate them into sections
17
+ map(&:strip). # Remove all whitespace
18
+ reject(&:empty?). # Get rid of indices that were only whitespace
19
+ # Lastly, separate the keys/value pairs for the Hash
20
+ map { |token| token =~ /^#{SECTION_TITLE}$/ ? token : token.split(/\n+/).sort }
21
+ ]
22
+ end
23
+
24
+ def warning_message
25
+ %{;; THIS FILE WAS GENERATED BY ADHEARSION ON #{Time.now.ctime}!\n} +
26
+ %{;; ANY CHANGES MADE BELOW WILL BE BLOWN AWAY WHEN THE FILE IS REGENERATED!\n\n}
27
+ end
28
+
29
+ end
30
+
31
+ def initialize
32
+ yield self if block_given?
33
+ end
34
+
35
+ def to_sanitary_hash
36
+ self.class.create_sanitary_hash_from to_s
37
+ end
38
+
39
+ protected
40
+
41
+ def boolean(options)
42
+ cache = options.delete(:with) || properties
43
+ options.each_pair do |key, value|
44
+ cache[key] = boolean_to_yes_no value
45
+ end
46
+ end
47
+
48
+ def string(options)
49
+ cache = options.delete(:with) || properties
50
+ options.each_pair do |key, value|
51
+ cache[key] = value
52
+ end
53
+ end
54
+
55
+ def int(options)
56
+ cache = options.delete(:with) || properties
57
+ options.each_pair do |property,number|
58
+ number = number.to_i if (number.kind_of?(String) && number =~ /^\d+$/) || number.kind_of?(Numeric)
59
+ raise ArgumentError, "#{number.inspect} must be an integer" unless number.kind_of?(Fixnum)
60
+ cache[property] = number.to_i
61
+ end
62
+ end
63
+
64
+ def one_of(criteria, options)
65
+ cache = options.delete(:with) || properties
66
+ options.each_pair do |key, value|
67
+ search = !criteria.find { |criterion| criterion === value }.nil?
68
+ unless search
69
+ msg = "Didn't recognize #{value.inspect}! Must be one of " + criteria.map(&:inspect).to_sentence
70
+ raise ArgumentError, msg
71
+ end
72
+ cache[key] = [true, false].include?(value) ? boolean_to_yes_no(value) : value
73
+ end
74
+ end
75
+
76
+ def one_of_and_translate(criteria, options)
77
+ cache = options.delete(:with) || properties
78
+ options.each_pair do |key, value|
79
+ search = criteria.keys.find { |criterion| criterion === value }
80
+ unless search
81
+ msg = "Didn't recognize #{value.inspect}! Must be one of " + criteria.keys.map(&:inspect).to_sentence
82
+ raise ArgumentError, msg
83
+ end
84
+ cache[key] = criteria[value]
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def boolean_to_yes_no(boolean)
91
+ unless boolean.equal?(boolean) || boolean.equal?(boolean)
92
+ raise "#{boolean.inspect} is not true/false!"
93
+ end
94
+ boolean ? 'yes' : 'no'
95
+ end
96
+
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,250 @@
1
+ require File.join(File.dirname(__FILE__), 'config_generator')
2
+
3
+ module Adhearsion
4
+ module VoIP
5
+ module Asterisk
6
+ module ConfigFileGenerators
7
+
8
+ # This will generate a queues.conf file. If there is no documentation on what a method
9
+ # actually does, take a look at the documentation for its original key/value pair in
10
+ # an unedited queues.conf file. WARNING! Don't get too embedded with these method names.
11
+ # I'm still not satisfied. These settings will be greatly abstracted eventually.
12
+ class Queues < AsteriskConfigGenerator
13
+
14
+ DEFAULT_GENERAL_SECTION = {
15
+ :autofill => "yes"
16
+ }
17
+
18
+ attr_reader :general_section, :queue_definitions, :properties
19
+ def initialize
20
+ @general_section = DEFAULT_GENERAL_SECTION.clone
21
+ @properties = {}
22
+ @queue_definitions = []
23
+ super
24
+ end
25
+
26
+ def queue(name)
27
+ new_queue = QueueDefinition.new name
28
+ yield new_queue if block_given?
29
+ queue_definitions << new_queue
30
+ new_queue
31
+ end
32
+
33
+ def to_s
34
+ AsteriskConfigGenerator.warning_message +
35
+ general_section.inject("[general]") { |section,(key,value)| section + "\n#{key}=#{value}" } + "\n\n" +
36
+ queue_definitions.map(&:to_s).join("\n\n")
37
+ end
38
+ alias conf to_s
39
+
40
+ def persistent_members(yes_no)
41
+ boolean :persistentmembers => yes_no, :with => general_section
42
+ end
43
+
44
+ def monitor_type(symbol)
45
+ criteria = {:monitor => "Monitor", :mix_monitor => "MixMonitor"}
46
+ one_of_and_translate criteria, 'monitor-type' => symbol, :with => general_section
47
+ end
48
+
49
+
50
+ class QueueDefinition < AsteriskConfigGenerator
51
+
52
+ DEFAULT_QUEUE_PROPERTIES = {
53
+ :autofill => 'yes',
54
+ :eventwhencalled => 'vars',
55
+ :eventmemberstatus => 'yes',
56
+ :setinterfacevar => 'yes'
57
+ }
58
+
59
+ SUPPORTED_RING_STRATEGIES = [:ringall, :roundrobin, :leastrecent, :fewestcalls, :random, :rrmemory]
60
+
61
+ DEFAULT_SOUND_FILES = {
62
+ 'queue-youarenext' => 'queue-youarenext',
63
+ 'queue-thereare' => 'queue-thereare',
64
+ 'queue-callswaiting' => 'queue-callswaiting',
65
+ 'queue-holdtime' => 'queue-holdtime',
66
+ 'queue-minutes' => 'queue-minutes',
67
+ 'queue-seconds' => 'queue-seconds',
68
+ 'queue-thankyou' => 'queue-thankyou',
69
+ 'queue-lessthan' => 'queue-less-than',
70
+ 'queue-reporthold' => 'queue-reporthold',
71
+ 'periodic-announce' => 'queue-periodic-announce'
72
+ }
73
+
74
+ SOUND_FILE_SYMBOL_INTERPRETATIONS = {
75
+ :you_are_next => 'queue-youarenext',
76
+ :there_are => 'queue-thereare',
77
+ :calls_waiting => 'queue-callswaiting',
78
+ :hold_time => 'queue-holdtime',
79
+ :minutes => 'queue-minutes',
80
+ :seconds => 'queue-seconds',
81
+ :thank_you => 'queue-thankyou',
82
+ :less_than => 'queue-lessthan',
83
+ :report_hold => 'queue-reporthold',
84
+ :periodic_announcement => 'periodic-announce'
85
+ }
86
+
87
+ attr_reader :members, :name, :properties
88
+ def initialize(name)
89
+ @name = name
90
+ @members = []
91
+ @properties = DEFAULT_QUEUE_PROPERTIES.clone
92
+ @sound_files = DEFAULT_SOUND_FILES.clone
93
+ end
94
+
95
+ def to_s
96
+ "[#{name}]\n" +
97
+ properties.merge(@sound_files).map { |key, value| "#{key}=#{value}" }.sort.join("\n") + "\n\n" +
98
+ members.map { |member| "member => #{member}" }.join("\n")
99
+ end
100
+
101
+ def music_class(moh_identifier)
102
+ string :musicclass => moh_identifier
103
+ end
104
+
105
+ def play_on_connect(sound_file)
106
+ string :announce => sound_file
107
+ end
108
+
109
+ def strategy(symbol)
110
+ one_of SUPPORTED_RING_STRATEGIES, :strategy => symbol
111
+ end
112
+
113
+ def service_level(seconds)
114
+ int :servicelevel => seconds
115
+ end
116
+
117
+ # A context may be specified, in which if the user types a SINGLE
118
+ # digit extension while they are in the queue, they will be taken out
119
+ # of the queue and sent to that extension in this context. This context
120
+ # should obviously be a different context other than the one that
121
+ # normally forwards to Adhearsion (though the context that handles
122
+ # these digits should probably go out to Adhearsion too).
123
+ def exit_to_context_on_digit_press(context_name)
124
+ string :context => context_name
125
+ end
126
+
127
+ # Ex: ring_timeout 15.seconds
128
+ def ring_timeout(seconds)
129
+ int :timeout => seconds
130
+ end
131
+
132
+ # Ex: retry_after_waiting 5.seconds
133
+ def retry_after_waiting(seconds)
134
+ int :retry => seconds
135
+ end
136
+
137
+ # THIS IS UNSUPPORTED
138
+ def weight(number)
139
+ int :weight => number
140
+ end
141
+
142
+ # Ex: wrapup_time 1.minute
143
+ def wrapup_time(seconds)
144
+ int :wrapuptime => seconds
145
+ end
146
+
147
+
148
+ def autopause(yes_no)
149
+ boolean :autopause => yes_no
150
+ end
151
+
152
+ def maximum_length(number)
153
+ int :maxlen => number
154
+ end
155
+
156
+ def queue_status_announce_frequency(seconds)
157
+ int "announce-frequency" => seconds
158
+ end
159
+
160
+ def periodically_announce(sound_file, options={})
161
+ frequency = options.delete(:every) || 1.minute
162
+
163
+ string 'periodic-announce' => sound_file
164
+ int 'periodic-announce-frequency' => frequency
165
+ end
166
+
167
+ def announce_hold_time(seconds)
168
+ one_of [true, false, :once], "announce-holdtime" => seconds
169
+ end
170
+
171
+ def announce_round_seconds(yes_no_or_once)
172
+ int "announce-round-seconds" => yes_no_or_once
173
+ end
174
+
175
+ def monitor_format(symbol)
176
+ one_of [:wav, :gsm, :wav49], 'monitor-format' => symbol
177
+ end
178
+
179
+ def monitor_type(symbol)
180
+ criteria = {:monitor => "Monitor", :mix_monitor => "MixMonitor"}
181
+ one_of_and_translate criteria, 'monitor-type' => symbol
182
+ end
183
+
184
+ # Ex: join_empty true
185
+ # Ex: join_empty :strict
186
+ def join_empty(yes_no_or_strict)
187
+ one_of [true, false, :strict], :joinempty => yes_no_or_strict
188
+ end
189
+
190
+ def leave_when_empty(yes_no)
191
+ boolean :leavewhenempty => yes_no
192
+ end
193
+
194
+ def report_hold_time(yes_no)
195
+ boolean :reportholdtime => yes_no
196
+ end
197
+
198
+ def ring_in_use(yes_no)
199
+ boolean :ringinuse => yes_no
200
+ end
201
+
202
+ # Number of seconds to wait when an agent is to be bridged with
203
+ # a caller. Normally you'd want this to be zero.
204
+ def delay_connection_by(seconds)
205
+ int :memberdelay => seconds
206
+ end
207
+
208
+ def timeout_restart(yes_no)
209
+ boolean :timeoutrestart => yes_no
210
+ end
211
+
212
+ # Give a Hash argument here to override the default sound files for this queue.
213
+ #
214
+ # Usage:
215
+ #
216
+ # queue.sound_files :you_are_next => 'queue-youarenext',
217
+ # :there_are => 'queue-thereare',
218
+ # :calls_waiting => 'queue-callswaiting',
219
+ # :hold_time => 'queue-holdtime',
220
+ # :minutes => 'queue-minutes',
221
+ # :seconds => 'queue-seconds',
222
+ # :thank_you => 'queue-thankyou',
223
+ # :less_than => 'queue-less-than',
224
+ # :report_hold => 'queue-reporthold',
225
+ # :periodic_announcement => 'queue-periodic-announce'
226
+ #
227
+ # Note: the Hash values are the defaults. You only need to specify the ones you
228
+ # wish to override.
229
+ def sound_files(hash_of_files)
230
+ hash_of_files.each_pair do |key, value|
231
+ unless SOUND_FILE_SYMBOL_INTERPRETATIONS.has_key? key
232
+ message = "Unrecogized sound file identifier #{key.inspect}. " +
233
+ "Supported: " + SOUND_FILE_SYMBOL_INTERPRETATIONS.keys.map(&:inspect).to_sentence
234
+ raise ArgumentError, message
235
+ end
236
+ @sound_files[SOUND_FILE_SYMBOL_INTERPRETATIONS[key]] = value
237
+ end
238
+ end
239
+
240
+ def member(driver)
241
+ members << (driver.kind_of?(String) && driver =~ %r'/' ? driver : "Agent/#{driver}")
242
+ end
243
+
244
+ end
245
+
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end