punchblock 2.0.0.beta1 → 2.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -5
- data/lib/punchblock/connection/asterisk.rb +1 -2
- data/lib/punchblock/connection/freeswitch.rb +1 -1
- data/lib/punchblock/core_ext/blather/stanza.rb +5 -4
- data/lib/punchblock/rayo_node.rb +2 -3
- data/lib/punchblock/translator/asterisk.rb +3 -3
- data/lib/punchblock/translator/asterisk/component/output.rb +1 -5
- data/lib/punchblock/translator/freeswitch.rb +5 -5
- data/lib/punchblock/translator/freeswitch/call.rb +9 -9
- data/lib/punchblock/translator/freeswitch/component/abstract_output.rb +2 -2
- data/lib/punchblock/translator/freeswitch/component/flite_output.rb +4 -0
- data/lib/punchblock/translator/freeswitch/component/tts_output.rb +7 -3
- data/lib/punchblock/version.rb +1 -1
- data/spec/punchblock/connection/asterisk_spec.rb +1 -6
- data/spec/punchblock/connection/freeswitch_spec.rb +3 -15
- data/spec/punchblock/connection/xmpp_spec.rb +37 -19
- data/spec/punchblock/translator/asterisk/component/composed_prompt_spec.rb +1 -2
- data/spec/punchblock/translator/asterisk/component/input_spec.rb +1 -2
- data/spec/punchblock/translator/asterisk/component/mrcp_native_prompt_spec.rb +1 -2
- data/spec/punchblock/translator/asterisk/component/mrcp_prompt_spec.rb +1 -2
- data/spec/punchblock/translator/asterisk/component/output_spec.rb +18 -47
- data/spec/punchblock/translator/asterisk/component/record_spec.rb +1 -2
- data/spec/punchblock/translator/asterisk_spec.rb +1 -12
- data/spec/punchblock/translator/freeswitch/call_spec.rb +19 -37
- data/spec/punchblock/translator/freeswitch/component/flite_output_spec.rb +4 -6
- data/spec/punchblock/translator/freeswitch/component/tts_output_spec.rb +6 -8
- data/spec/punchblock/translator/freeswitch_spec.rb +1 -7
- data/spec/spec_helper.rb +4 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f0d1de96c4233bf0c4b8ed7943e4dc93e23138c
|
4
|
+
data.tar.gz: 57aeccc7ef70667f12f582f96b9a40e357d1e1f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 605b57ffde8d82ceb9fc87f625a21c1c9ac55fc32135a4d3bd9c3b689febabe4741e8877a7eeae2f0c5bd9861583bce9643d17289d5a5b15d79ac91f254cf0d5
|
7
|
+
data.tar.gz: 57030a3403b343c3c6846d1b2bd958837ccca4caf25afbef8a2babad25a0b17e25ad17790d5d5680a303bb4a8695ce73357e17dd7a5e6da9e1b1f238f39c4941
|
data/CHANGELOG.md
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# [develop](https://github.com/adhearsion/punchblock)
|
2
2
|
|
3
|
-
# [v2.0.0.
|
4
|
-
* Bugfix: Reconnect dead Asterisk streams correctly
|
5
|
-
* Feature: Added FS support for initial timeout and final timeout on Record.
|
3
|
+
# [v2.0.0.beta2](https://github.com/adhearsion/punchblock/compare/v1.9.4...v2.0.0.beta2) - [2013-08-27](https://rubygems.org/gems/punchblock/versions/2.0.0.beta2)
|
6
4
|
* Feature: Compliance with v0.2 of the published Rayo spec (http://xmpp.org/extensions/xep-0327.html)
|
7
|
-
* Feature: Add support for Rayo Prompt component
|
5
|
+
* Feature: Add support for Rayo Prompt component
|
6
|
+
* Feature: Added FS support for initial timeout and final timeout on Record
|
8
7
|
* Change: Models are now plain ruby objects, not XML nodes, and are imported from/exported to XML when necessary for communicating over XMPP.
|
9
8
|
* Change: `#headers` and AMI `#attributes` now do not have their names modified. A header of `'Call-ID'` will no longer be modified to `:call_id`.
|
10
9
|
* Change: AMI Events/Actions now have `#headers(=)` rather than `#attributes(=)`
|
11
10
|
* Change: Remove event queue
|
11
|
+
* Change: Removed `media_engine` and `default_voice` settings
|
12
|
+
* Bugfix: Reconnect dead Asterisk streams correctly
|
12
13
|
* Bugfix: Include AMI response text_body in AMI component complete events
|
13
14
|
* Bugfix: Avoid crashing translators (Asterisk or FreeSWITCH) by instructing them to call back to terminated Call objects
|
14
|
-
* Bugfix: Detect MRCPSynth failure in output component
|
15
|
+
* Bugfix: Detect MRCPSynth failure in output component
|
15
16
|
* Bugfix: Handle AMI errors indicating dead channels correctly
|
16
17
|
|
17
18
|
# [v1.9.4](https://github.com/adhearsion/punchblock/compare/v1.9.3...v1.9.4) - [2013-06-08](https://rubygems.org/gems/punchblock/versions/1.9.4)
|
@@ -10,9 +10,8 @@ module Punchblock
|
|
10
10
|
|
11
11
|
def initialize(options = {})
|
12
12
|
@stream_options = options.values_at(:host, :port, :username, :password)
|
13
|
-
@translator_options = options.values_at(:media_engine)
|
14
13
|
@ami_client = new_ami_stream
|
15
|
-
@translator = Translator::Asterisk.new @ami_client, self
|
14
|
+
@translator = Translator::Asterisk.new @ami_client, self
|
16
15
|
super()
|
17
16
|
end
|
18
17
|
|
@@ -9,7 +9,7 @@ module Punchblock
|
|
9
9
|
attr_accessor :event_handler
|
10
10
|
|
11
11
|
def initialize(options = {})
|
12
|
-
@translator = Translator::Freeswitch.new self
|
12
|
+
@translator = Translator::Freeswitch.new self
|
13
13
|
@stream_options = options.values_at(:host, :port, :password)
|
14
14
|
@stream = new_fs_stream
|
15
15
|
super()
|
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
module Blather
|
4
4
|
class Stanza
|
5
|
+
RAYO_NODE_PATH = "(#{Punchblock::RAYO_NAMESPACES.keys.map { |k| "#{k}:*" }.join("|")})".freeze
|
5
6
|
##
|
6
7
|
# @return [Punchblock::RayoNode] a child of RayoNode
|
7
8
|
# representing the Rayo command/event contained within the stanza
|
8
9
|
#
|
9
10
|
def rayo_node
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
@rayo_node ||= begin
|
12
|
+
first_child = at_xpath RAYO_NODE_PATH, Punchblock::RAYO_NAMESPACES
|
13
|
+
Punchblock::RayoNode.from_xml first_child, nil, component_id if first_child
|
14
|
+
end
|
14
15
|
end
|
15
16
|
|
16
17
|
##
|
data/lib/punchblock/rayo_node.rb
CHANGED
@@ -7,8 +7,6 @@ module Punchblock
|
|
7
7
|
class RayoNode
|
8
8
|
include Virtus
|
9
9
|
|
10
|
-
InvalidNodeError = Class.new Punchblock::Error
|
11
|
-
|
12
10
|
@@registrations = {}
|
13
11
|
|
14
12
|
class_attribute :registered_ns, :registered_name
|
@@ -65,7 +63,8 @@ module Punchblock
|
|
65
63
|
|
66
64
|
def inherit(xml_node)
|
67
65
|
xml_node.attributes.each do |key, attr_node|
|
68
|
-
|
66
|
+
setter_method = "#{key.gsub('-', '_')}="
|
67
|
+
send setter_method, xml_node[key] if respond_to?(setter_method)
|
69
68
|
end
|
70
69
|
self
|
71
70
|
end
|
@@ -18,7 +18,7 @@ module Punchblock
|
|
18
18
|
autoload :Channel
|
19
19
|
autoload :Component
|
20
20
|
|
21
|
-
attr_reader :ami_client, :connection, :
|
21
|
+
attr_reader :ami_client, :connection, :calls
|
22
22
|
|
23
23
|
REDIRECT_CONTEXT = 'adhearsion-redirect'
|
24
24
|
REDIRECT_EXTENSION = '1'
|
@@ -28,8 +28,8 @@ module Punchblock
|
|
28
28
|
|
29
29
|
trap_exit :actor_died
|
30
30
|
|
31
|
-
def initialize(ami_client, connection
|
32
|
-
@ami_client, @connection
|
31
|
+
def initialize(ami_client, connection)
|
32
|
+
@ami_client, @connection = ami_client, connection
|
33
33
|
@calls, @components, @channel_to_call_id = {}, {}, {}
|
34
34
|
end
|
35
35
|
|
@@ -14,10 +14,6 @@ module Punchblock
|
|
14
14
|
UniMRCPError = Class.new Punchblock::Error
|
15
15
|
PlaybackError = Class.new Punchblock::Error
|
16
16
|
|
17
|
-
def setup
|
18
|
-
@media_engine = @call.translator.media_engine
|
19
|
-
end
|
20
|
-
|
21
17
|
def execute
|
22
18
|
raise OptionError, 'An SSML document is required.' unless @component_node.render_documents.first.value
|
23
19
|
raise OptionError, 'Only a single document is supported.' unless @component_node.render_documents.size == 1
|
@@ -29,7 +25,7 @@ module Punchblock
|
|
29
25
|
|
30
26
|
early = !@call.answered?
|
31
27
|
|
32
|
-
rendering_engine = @component_node.renderer ||
|
28
|
+
rendering_engine = @component_node.renderer || :asterisk
|
33
29
|
|
34
30
|
case rendering_engine.to_sym
|
35
31
|
when :asterisk
|
@@ -18,14 +18,14 @@ module Punchblock
|
|
18
18
|
autoload :Call
|
19
19
|
autoload :Component
|
20
20
|
|
21
|
-
attr_reader :connection, :
|
21
|
+
attr_reader :connection, :calls
|
22
22
|
|
23
23
|
trap_exit :actor_died
|
24
24
|
|
25
25
|
finalizer :finalize
|
26
26
|
|
27
|
-
def initialize(connection
|
28
|
-
@connection
|
27
|
+
def initialize(connection)
|
28
|
+
@connection = connection
|
29
29
|
@calls, @components = {}, {}
|
30
30
|
setup_handlers
|
31
31
|
end
|
@@ -62,7 +62,7 @@ module Punchblock
|
|
62
62
|
|
63
63
|
register_handler :es, :event_name => 'CHANNEL_PARK' do |event|
|
64
64
|
throw :pass if es_event_known_call? event
|
65
|
-
call = Call.new event[:unique_id], current_actor, event.content.select { |k,v| k.to_s =~ /variable/ }, stream
|
65
|
+
call = Call.new event[:unique_id], current_actor, event.content.select { |k,v| k.to_s =~ /variable/ }, stream
|
66
66
|
link call
|
67
67
|
register_call call
|
68
68
|
call.async.send_offer
|
@@ -135,7 +135,7 @@ module Punchblock
|
|
135
135
|
def execute_global_command(command)
|
136
136
|
case command
|
137
137
|
when Punchblock::Command::Dial
|
138
|
-
call = Call.new_link Punchblock.new_uuid, current_actor, nil, stream
|
138
|
+
call = Call.new_link Punchblock.new_uuid, current_actor, nil, stream
|
139
139
|
register_call call
|
140
140
|
call.async.dial command
|
141
141
|
else
|
@@ -37,12 +37,12 @@ module Punchblock
|
|
37
37
|
REJECT_TO_HANGUP_REASON = Hash.new 'NORMAL_TEMPORARY_FAILURE'
|
38
38
|
REJECT_TO_HANGUP_REASON.merge! :busy => 'USER_BUSY', :decline => 'CALL_REJECTED'
|
39
39
|
|
40
|
-
attr_reader :id, :translator, :es_env, :direction, :stream
|
40
|
+
attr_reader :id, :translator, :es_env, :direction, :stream
|
41
41
|
|
42
42
|
trap_exit :actor_died
|
43
43
|
|
44
|
-
def initialize(id, translator, es_env = nil, stream = nil
|
45
|
-
@id, @translator, @stream
|
44
|
+
def initialize(id, translator, es_env = nil, stream = nil)
|
45
|
+
@id, @translator, @stream = id, translator, stream
|
46
46
|
@es_env = es_env || {}
|
47
47
|
@components = {}
|
48
48
|
@pending_joins, @pending_unjoins = {}, {}
|
@@ -205,14 +205,14 @@ module Punchblock
|
|
205
205
|
hangup REJECT_TO_HANGUP_REASON[command.reason]
|
206
206
|
command.response = true
|
207
207
|
when Punchblock::Component::Output
|
208
|
-
media_renderer = command.renderer ||
|
209
|
-
case media_renderer.
|
210
|
-
when
|
208
|
+
media_renderer = command.renderer || :freeswitch
|
209
|
+
case media_renderer.to_s
|
210
|
+
when 'freeswitch', 'native'
|
211
211
|
execute_component Component::Output, command
|
212
|
-
when
|
213
|
-
execute_component Component::FliteOutput, command
|
212
|
+
when 'flite'
|
213
|
+
execute_component Component::FliteOutput, command
|
214
214
|
else
|
215
|
-
execute_component Component::TTSOutput, command
|
215
|
+
execute_component Component::TTSOutput, command
|
216
216
|
end
|
217
217
|
when Punchblock::Component::Input
|
218
218
|
execute_component Component::Input, command
|
@@ -7,10 +7,10 @@ module Punchblock
|
|
7
7
|
class AbstractOutput < Component
|
8
8
|
UnrenderableDocError = Class.new OptionError
|
9
9
|
|
10
|
-
def execute
|
10
|
+
def execute
|
11
11
|
validate
|
12
12
|
send_ref
|
13
|
-
do_output
|
13
|
+
do_output
|
14
14
|
rescue UnrenderableDocError => e
|
15
15
|
with_error 'unrenderable document error', e.message
|
16
16
|
rescue OptionError => e
|
@@ -7,12 +7,16 @@ module Punchblock
|
|
7
7
|
class TTSOutput < AbstractOutput
|
8
8
|
private
|
9
9
|
|
10
|
-
def do_output
|
10
|
+
def do_output
|
11
11
|
register_handler :es, :event_name => 'CHANNEL_EXECUTE_COMPLETE' do |event|
|
12
12
|
send_complete_event finish_reason
|
13
13
|
end
|
14
|
-
voice = @component_node.voice ||
|
15
|
-
application :speak, [
|
14
|
+
voice = @component_node.voice || :kal
|
15
|
+
application :speak, [renderer, voice, document].join('|')
|
16
|
+
end
|
17
|
+
|
18
|
+
def renderer
|
19
|
+
@component_node.renderer || :flite
|
16
20
|
end
|
17
21
|
|
18
22
|
def document
|
data/lib/punchblock/version.rb
CHANGED
@@ -10,8 +10,7 @@ module Punchblock
|
|
10
10
|
:host => '127.0.0.1',
|
11
11
|
:port => 5038,
|
12
12
|
:username => 'test',
|
13
|
-
:password => 'test'
|
14
|
-
:media_engine => :swift
|
13
|
+
:password => 'test'
|
15
14
|
}
|
16
15
|
end
|
17
16
|
|
@@ -32,10 +31,6 @@ module Punchblock
|
|
32
31
|
subject.translator.connection.should be subject
|
33
32
|
end
|
34
33
|
|
35
|
-
it 'should set the media engine on the translator' do
|
36
|
-
subject.translator.media_engine.should be == :swift
|
37
|
-
end
|
38
|
-
|
39
34
|
describe '#run' do
|
40
35
|
it 'starts the RubyAMI::Stream' do
|
41
36
|
subject.ami_client.async.should_receive(:run).once do
|
@@ -5,15 +5,11 @@ require 'spec_helper'
|
|
5
5
|
module Punchblock
|
6
6
|
module Connection
|
7
7
|
describe Freeswitch do
|
8
|
-
let(:media_engine) { :flite }
|
9
|
-
let(:default_voice) { :hal }
|
10
8
|
let :options do
|
11
9
|
{
|
12
|
-
:host
|
13
|
-
:port
|
14
|
-
:password
|
15
|
-
:media_engine => media_engine,
|
16
|
-
:default_voice => default_voice
|
10
|
+
:host => '127.0.0.1',
|
11
|
+
:port => 8021,
|
12
|
+
:password => 'test'
|
17
13
|
}
|
18
14
|
end
|
19
15
|
|
@@ -33,14 +29,6 @@ module Punchblock
|
|
33
29
|
subject.translator.connection.should be subject
|
34
30
|
end
|
35
31
|
|
36
|
-
it 'should set the media engine on the translator' do
|
37
|
-
subject.translator.media_engine.should be media_engine
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'should set the default voice on the translator' do
|
41
|
-
subject.translator.default_voice.should be default_voice
|
42
|
-
end
|
43
|
-
|
44
32
|
describe '#run' do
|
45
33
|
it 'starts a RubyFS stream' do
|
46
34
|
# subject.should_receive(:new_fs_stream).once.with('127.0.0.1', 8021, 'test').and_return mock_stream
|
@@ -125,21 +125,6 @@ module Punchblock
|
|
125
125
|
end
|
126
126
|
|
127
127
|
describe '#handle_presence' do
|
128
|
-
let :offer_xml do
|
129
|
-
<<-MSG
|
130
|
-
<presence to='16577@app.rayo.net/1' from='9f00061@call.rayo.net'>
|
131
|
-
<offer xmlns="urn:xmpp:rayo:1" to="sip:whatever@127.0.0.1" from="sip:ylcaomxb@192.168.1.9">
|
132
|
-
<header name="Max-Forwards" value="70"/>
|
133
|
-
<header name="Content-Length" value="367"/>
|
134
|
-
</offer>
|
135
|
-
</presence>
|
136
|
-
MSG
|
137
|
-
end
|
138
|
-
|
139
|
-
let(:example_offer) { import_stanza offer_xml }
|
140
|
-
|
141
|
-
it { example_offer.should be_a Blather::Stanza::Presence }
|
142
|
-
|
143
128
|
let :complete_xml do
|
144
129
|
<<-MSG
|
145
130
|
<presence to='16577@app.rayo.net/1' from='9f00061@call.rayo.net/fgh4590'>
|
@@ -154,9 +139,34 @@ module Punchblock
|
|
154
139
|
|
155
140
|
it { example_complete.should be_a Blather::Stanza::Presence }
|
156
141
|
|
142
|
+
describe "accessing the rayo node for a presence stanza" do
|
143
|
+
it "should import the rayo node" do
|
144
|
+
example_complete.rayo_node.should be_a Punchblock::Event::Complete
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should be memoized" do
|
148
|
+
example_complete.rayo_node.should be example_complete.rayo_node
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
157
152
|
describe "presence received" do
|
153
|
+
let(:handle_presence) { connection.__send__ :handle_presence, example_event }
|
154
|
+
|
158
155
|
describe "from an offer" do
|
159
|
-
let
|
156
|
+
let :offer_xml do
|
157
|
+
<<-MSG
|
158
|
+
<presence to='16577@app.rayo.net/1' from='9f00061@call.rayo.net'>
|
159
|
+
<offer xmlns="urn:xmpp:rayo:1" to="sip:whatever@127.0.0.1" from="sip:ylcaomxb@192.168.1.9">
|
160
|
+
<header name="Max-Forwards" value="70"/>
|
161
|
+
<header name="Content-Length" value="367"/>
|
162
|
+
</offer>
|
163
|
+
</presence>
|
164
|
+
MSG
|
165
|
+
end
|
166
|
+
|
167
|
+
let(:example_event) { import_stanza offer_xml }
|
168
|
+
|
169
|
+
it { example_event.should be_a Blather::Stanza::Presence }
|
160
170
|
|
161
171
|
it 'should call the event handler with the event' do
|
162
172
|
mock_event_handler.should_receive(:call).once.with do |event|
|
@@ -173,16 +183,24 @@ module Punchblock
|
|
173
183
|
let :irrelevant_xml do
|
174
184
|
<<-MSG
|
175
185
|
<presence to='16577@app.rayo.net/1' from='9f00061@call.rayo.net/fgh4590'>
|
176
|
-
<foo/>
|
186
|
+
<foo bar="baz"/>
|
177
187
|
</presence>
|
178
188
|
MSG
|
179
189
|
end
|
180
190
|
|
181
|
-
let(:
|
191
|
+
let(:example_event) { import_stanza irrelevant_xml }
|
192
|
+
|
193
|
+
it 'should not be considered to be a rayo event' do
|
194
|
+
example_event.rayo_event?.should be_false
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should have a nil rayo_node' do
|
198
|
+
example_event.rayo_node.should be_nil
|
199
|
+
end
|
182
200
|
|
183
201
|
it 'should not handle the event' do
|
184
202
|
mock_event_handler.should_receive(:call).never
|
185
|
-
lambda {
|
203
|
+
lambda { handle_presence }.should throw_symbol(:pass)
|
186
204
|
end
|
187
205
|
end
|
188
206
|
end
|
@@ -20,9 +20,8 @@ module Punchblock
|
|
20
20
|
end
|
21
21
|
|
22
22
|
let(:connection) { MockConnection.new }
|
23
|
-
let(:media_engine) { nil }
|
24
23
|
let(:ami_client) { double('AMI') }
|
25
|
-
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection
|
24
|
+
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection }
|
26
25
|
let(:call) { Punchblock::Translator::Asterisk::Call.new 'foo', translator, ami_client, connection }
|
27
26
|
|
28
27
|
let :ssml_doc do
|
@@ -9,9 +9,8 @@ module Punchblock
|
|
9
9
|
describe Input do
|
10
10
|
include HasMockCallbackConnection
|
11
11
|
|
12
|
-
let(:media_engine) { nil }
|
13
12
|
let(:ami_client) { double('AMI') }
|
14
|
-
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection
|
13
|
+
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection }
|
15
14
|
let(:call) { Punchblock::Translator::Asterisk::Call.new 'foo', translator, ami_client, connection }
|
16
15
|
let(:original_command_options) { {} }
|
17
16
|
|
@@ -9,9 +9,8 @@ module Punchblock
|
|
9
9
|
describe MRCPNativePrompt do
|
10
10
|
include HasMockCallbackConnection
|
11
11
|
|
12
|
-
let(:media_engine) { :unimrcp }
|
13
12
|
let(:ami_client) { double('AMI') }
|
14
|
-
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection
|
13
|
+
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection }
|
15
14
|
let(:mock_call) { Punchblock::Translator::Asterisk::Call.new 'foo', translator, ami_client, connection }
|
16
15
|
|
17
16
|
let :ssml_doc do
|
@@ -9,9 +9,8 @@ module Punchblock
|
|
9
9
|
describe MRCPPrompt do
|
10
10
|
include HasMockCallbackConnection
|
11
11
|
|
12
|
-
let(:media_engine) { :unimrcp }
|
13
12
|
let(:ami_client) { double('AMI') }
|
14
|
-
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection
|
13
|
+
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection }
|
15
14
|
let(:mock_call) { Punchblock::Translator::Asterisk::Call.new 'foo', translator, ami_client, connection }
|
16
15
|
|
17
16
|
let :ssml_doc do
|
@@ -9,10 +9,10 @@ module Punchblock
|
|
9
9
|
describe Output do
|
10
10
|
include HasMockCallbackConnection
|
11
11
|
|
12
|
-
let(:
|
13
|
-
let(:ami_client)
|
14
|
-
let(:translator)
|
15
|
-
let(:mock_call)
|
12
|
+
let(:renderer) { nil }
|
13
|
+
let(:ami_client) { double('AMI') }
|
14
|
+
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection }
|
15
|
+
let(:mock_call) { Punchblock::Translator::Asterisk::Call.new 'foo', translator, ami_client, connection }
|
16
16
|
|
17
17
|
let :original_command do
|
18
18
|
Punchblock::Component::Output.new command_options
|
@@ -24,8 +24,10 @@ module Punchblock
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
let(:command_opts) { {} }
|
28
|
+
|
27
29
|
let :command_options do
|
28
|
-
{ :render_document => {:value => ssml_doc} }
|
30
|
+
{ :render_document => {:value => ssml_doc}, renderer: renderer }
|
29
31
|
end
|
30
32
|
|
31
33
|
subject { Output.new original_command, mock_call }
|
@@ -37,8 +39,8 @@ module Punchblock
|
|
37
39
|
describe '#execute' do
|
38
40
|
before { original_command.request! }
|
39
41
|
|
40
|
-
context 'with an invalid
|
41
|
-
let(:
|
42
|
+
context 'with an invalid renderer' do
|
43
|
+
let(:renderer) { 'foobar' }
|
42
44
|
|
43
45
|
it "should return an error and not execute any actions" do
|
44
46
|
subject.execute
|
@@ -47,8 +49,8 @@ module Punchblock
|
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
|
-
context 'with a
|
51
|
-
let(:
|
52
|
+
context 'with a renderer of :swift' do
|
53
|
+
let(:renderer) { 'swift' }
|
52
54
|
|
53
55
|
let(:audio_filename) { 'http://foo.com/bar.mp3' }
|
54
56
|
|
@@ -59,10 +61,8 @@ module Punchblock
|
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
62
|
-
let(:command_opts) { {} }
|
63
|
-
|
64
64
|
let :command_options do
|
65
|
-
{ :render_document => {:value => ssml_doc} }.merge(command_opts)
|
65
|
+
{ :render_document => {:value => ssml_doc}, renderer: renderer }.merge(command_opts)
|
66
66
|
end
|
67
67
|
|
68
68
|
def ssml_with_options(prefix = '', postfix = '')
|
@@ -169,8 +169,8 @@ module Punchblock
|
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
|
-
context 'with a
|
173
|
-
let(:
|
172
|
+
context 'with a renderer of :unimrcp' do
|
173
|
+
let(:renderer) { :unimrcp }
|
174
174
|
|
175
175
|
let(:audio_filename) { 'http://foo.com/bar.mp3' }
|
176
176
|
|
@@ -184,7 +184,7 @@ module Punchblock
|
|
184
184
|
let(:command_opts) { {} }
|
185
185
|
|
186
186
|
let :command_options do
|
187
|
-
{ :render_document => {:value => ssml_doc} }.merge(command_opts)
|
187
|
+
{ :render_document => {:value => ssml_doc}, renderer: renderer }.merge(command_opts)
|
188
188
|
end
|
189
189
|
|
190
190
|
let(:synthstatus) { 'OK' }
|
@@ -422,8 +422,8 @@ module Punchblock
|
|
422
422
|
end
|
423
423
|
end
|
424
424
|
|
425
|
-
[:asterisk, nil].each do |
|
426
|
-
context "with a
|
425
|
+
[:asterisk, nil].each do |renderer|
|
426
|
+
context "with a renderer of #{renderer.inspect}" do
|
427
427
|
def expect_playback(filename = audio_filename)
|
428
428
|
mock_call.should_receive(:execute_agi_command).once.with('EXEC Playback', filename).and_return code: 200
|
429
429
|
end
|
@@ -443,7 +443,7 @@ module Punchblock
|
|
443
443
|
let(:command_opts) { {} }
|
444
444
|
|
445
445
|
let :command_options do
|
446
|
-
{ :render_document => {:value => ssml_doc} }.merge(command_opts)
|
446
|
+
{ :render_document => {:value => ssml_doc}, renderer: renderer }.merge(command_opts)
|
447
447
|
end
|
448
448
|
|
449
449
|
let :original_command do
|
@@ -864,35 +864,6 @@ module Punchblock
|
|
864
864
|
end
|
865
865
|
end
|
866
866
|
end
|
867
|
-
|
868
|
-
context "with a media renderer set on itself" do
|
869
|
-
let(:media_engine) { :swift }
|
870
|
-
let(:audio_filename) { '/foo/bar.wav' }
|
871
|
-
let :ssml_doc do
|
872
|
-
RubySpeech::SSML.draw do
|
873
|
-
audio :src => audio_filename
|
874
|
-
end
|
875
|
-
end
|
876
|
-
|
877
|
-
let(:command_opts) { {:renderer => :asterisk} }
|
878
|
-
|
879
|
-
let :command_options do
|
880
|
-
{ :render_document => {:value => ssml_doc} }.merge(command_opts)
|
881
|
-
end
|
882
|
-
|
883
|
-
let :original_command do
|
884
|
-
Punchblock::Component::Output.new command_options
|
885
|
-
end
|
886
|
-
|
887
|
-
let(:playbackstatus) { 'SUCCESS' }
|
888
|
-
before { mock_call.stub(:channel_var).with('PLAYBACKSTATUS').and_return playbackstatus }
|
889
|
-
|
890
|
-
it "should use the media renderer set and not the platform default" do
|
891
|
-
expect_answered
|
892
|
-
mock_call.should_receive(:execute_agi_command).once.with 'EXEC Playback', audio_filename
|
893
|
-
subject.execute
|
894
|
-
end
|
895
|
-
end
|
896
867
|
end
|
897
868
|
|
898
869
|
describe "#execute_command" do
|
@@ -9,10 +9,9 @@ module Punchblock
|
|
9
9
|
describe Record do
|
10
10
|
include HasMockCallbackConnection
|
11
11
|
|
12
|
-
let(:media_engine) { nil }
|
13
12
|
let(:channel) { 'SIP/foo' }
|
14
13
|
let(:ami_client) { double('AMI Client').as_null_object }
|
15
|
-
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection
|
14
|
+
let(:translator) { Punchblock::Translator::Asterisk.new ami_client, connection }
|
16
15
|
let(:mock_call) { Punchblock::Translator::Asterisk::Call.new channel, translator, ami_client, connection }
|
17
16
|
|
18
17
|
let :original_command do
|
@@ -8,9 +8,8 @@ module Punchblock
|
|
8
8
|
describe Asterisk do
|
9
9
|
let(:ami_client) { double 'RubyAMI::Client' }
|
10
10
|
let(:connection) { double 'Connection::Asterisk', handle_event: nil }
|
11
|
-
let(:media_engine) { :asterisk }
|
12
11
|
|
13
|
-
let(:translator) { Asterisk.new ami_client, connection
|
12
|
+
let(:translator) { Asterisk.new ami_client, connection }
|
14
13
|
|
15
14
|
subject { translator }
|
16
15
|
|
@@ -19,16 +18,6 @@ module Punchblock
|
|
19
18
|
|
20
19
|
after { translator.terminate if translator.alive? }
|
21
20
|
|
22
|
-
context 'with a configured media engine of :asterisk' do
|
23
|
-
let(:media_engine) { :asterisk }
|
24
|
-
its(:media_engine) { should be == :asterisk }
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'with a configured media engine of :unimrcp' do
|
28
|
-
let(:media_engine) { :unimrcp }
|
29
|
-
its(:media_engine) { should be == :unimrcp }
|
30
|
-
end
|
31
|
-
|
32
21
|
describe '#shutdown' do
|
33
22
|
it "instructs all calls to shutdown" do
|
34
23
|
call = Asterisk::Call.new 'foo', subject, ami_client, connection
|
@@ -6,10 +6,8 @@ module Punchblock
|
|
6
6
|
module Translator
|
7
7
|
class Freeswitch
|
8
8
|
describe Call do
|
9
|
-
let(:id)
|
9
|
+
let(:id) { Punchblock.new_uuid }
|
10
10
|
let(:stream) { double('RubyFS::Stream').as_null_object }
|
11
|
-
let(:media_engine) { 'freeswitch' }
|
12
|
-
let(:default_voice) { :hal }
|
13
11
|
let(:translator) { Freeswitch.new double('Connection::Freeswitch').as_null_object }
|
14
12
|
let(:es_env) do
|
15
13
|
{
|
@@ -165,13 +163,12 @@ module Punchblock
|
|
165
163
|
}
|
166
164
|
end
|
167
165
|
|
168
|
-
subject { Call.new id, translator, es_env, stream
|
166
|
+
subject { Call.new id, translator, es_env, stream }
|
169
167
|
|
170
|
-
its(:id)
|
171
|
-
its(:translator)
|
172
|
-
its(:es_env)
|
173
|
-
its(:stream)
|
174
|
-
its(:media_engine) { should be media_engine }
|
168
|
+
its(:id) { should be == id }
|
169
|
+
its(:translator) { should be translator }
|
170
|
+
its(:es_env) { should be == es_env }
|
171
|
+
its(:stream) { should be stream }
|
175
172
|
|
176
173
|
describe '#register_component' do
|
177
174
|
it 'should make the component accessible by ID' do
|
@@ -777,15 +774,15 @@ module Punchblock
|
|
777
774
|
|
778
775
|
context 'with an Output component' do
|
779
776
|
let :command do
|
780
|
-
Punchblock::Component::Output.new
|
777
|
+
Punchblock::Component::Output.new renderer: renderer
|
781
778
|
end
|
782
779
|
|
783
780
|
let(:mock_component) { Translator::Freeswitch::Component::Output.new(command, subject) }
|
784
781
|
|
785
|
-
['freeswitch', nil].each do |
|
786
|
-
let(:
|
782
|
+
['freeswitch', 'native', nil].each do |renderer|
|
783
|
+
let(:renderer) { renderer }
|
787
784
|
|
788
|
-
context "with a
|
785
|
+
context "with a renderer of #{renderer}" do
|
789
786
|
it 'should create an Output component and execute it asynchronously' do
|
790
787
|
Component::Output.should_receive(:new_link).once.with(command, subject).and_return mock_component
|
791
788
|
mock_component.should_receive(:execute).once
|
@@ -795,50 +792,35 @@ module Punchblock
|
|
795
792
|
end
|
796
793
|
end
|
797
794
|
|
798
|
-
context 'with the
|
799
|
-
let(:
|
795
|
+
context 'with the renderer of :flite' do
|
796
|
+
let(:renderer) { :flite }
|
800
797
|
|
801
798
|
it 'should create a FliteOutput component and execute it asynchronously using flite and the calls default voice' do
|
802
799
|
Component::FliteOutput.should_receive(:new_link).once.with(command, subject).and_return mock_component
|
803
|
-
mock_component.should_receive(:execute).once
|
800
|
+
mock_component.should_receive(:execute).once
|
804
801
|
subject.execute_command command
|
805
802
|
subject.component_with_id(mock_component.id).should be mock_component
|
806
803
|
end
|
807
804
|
end
|
808
805
|
|
809
|
-
context 'with the
|
810
|
-
let(:
|
806
|
+
context 'with the renderer of :cepstral' do
|
807
|
+
let(:renderer) { :cepstral }
|
811
808
|
|
812
809
|
it 'should create a TTSOutput component and execute it asynchronously using cepstral and the calls default voice' do
|
813
810
|
Component::TTSOutput.should_receive(:new_link).once.with(command, subject).and_return mock_component
|
814
|
-
mock_component.should_receive(:execute).once
|
811
|
+
mock_component.should_receive(:execute).once
|
815
812
|
subject.execute_command command
|
816
813
|
subject.component_with_id(mock_component.id).should be mock_component
|
817
814
|
end
|
818
815
|
end
|
819
816
|
|
820
|
-
context 'with the
|
821
|
-
let(:
|
817
|
+
context 'with the renderer of :unimrcp' do
|
818
|
+
let(:renderer) { :unimrcp }
|
822
819
|
|
823
820
|
it 'should create a TTSOutput component and execute it asynchronously using unimrcp and the calls default voice' do
|
824
821
|
Component::TTSOutput.should_receive(:new_link).once.with(command, subject).and_return mock_component
|
825
|
-
mock_component.should_receive(:execute).once.with(media_engine, default_voice)
|
826
|
-
subject.execute_command command
|
827
|
-
subject.component_with_id(mock_component.id).should be mock_component
|
828
|
-
end
|
829
|
-
end
|
830
|
-
|
831
|
-
context "with a media renderer set on the component" do
|
832
|
-
let(:media_engine) { :cepstral }
|
833
|
-
let(:media_renderer) { :native }
|
834
|
-
let :command_with_renderer do
|
835
|
-
Punchblock::Component::Output.new :renderer => media_renderer
|
836
|
-
end
|
837
|
-
|
838
|
-
it "should use the component media engine and not the platform one if it is set" do
|
839
|
-
Component::Output.should_receive(:new_link).once.with(command_with_renderer, subject).and_return mock_component
|
840
822
|
mock_component.should_receive(:execute).once
|
841
|
-
subject.execute_command
|
823
|
+
subject.execute_command command
|
842
824
|
subject.component_with_id(mock_component.id).should be mock_component
|
843
825
|
end
|
844
826
|
end
|
@@ -9,10 +9,8 @@ module Punchblock
|
|
9
9
|
describe FliteOutput do
|
10
10
|
include HasMockCallbackConnection
|
11
11
|
|
12
|
-
let(:
|
13
|
-
let(:
|
14
|
-
let(:translator) { Punchblock::Translator::Freeswitch.new connection }
|
15
|
-
let(:mock_call) { Punchblock::Translator::Freeswitch::Call.new 'foo', translator }
|
12
|
+
let(:translator) { Punchblock::Translator::Freeswitch.new connection }
|
13
|
+
let(:mock_call) { Punchblock::Translator::Freeswitch::Call.new 'foo', translator }
|
16
14
|
|
17
15
|
let :original_command do
|
18
16
|
Punchblock::Component::Output.new command_options
|
@@ -29,7 +27,7 @@ module Punchblock
|
|
29
27
|
end
|
30
28
|
|
31
29
|
def execute
|
32
|
-
subject.execute
|
30
|
+
subject.execute
|
33
31
|
end
|
34
32
|
|
35
33
|
subject { described_class.new original_command, mock_call }
|
@@ -37,7 +35,7 @@ module Punchblock
|
|
37
35
|
describe '#execute' do
|
38
36
|
before { original_command.request! }
|
39
37
|
def expect_playback(voice = :kal)
|
40
|
-
subject.wrapped_object.should_receive(:application).once.with :speak, "
|
38
|
+
subject.wrapped_object.should_receive(:application).once.with :speak, "flite|#{voice}|FOO"
|
41
39
|
end
|
42
40
|
|
43
41
|
let(:command_opts) { {} }
|
@@ -9,10 +9,8 @@ module Punchblock
|
|
9
9
|
describe TTSOutput do
|
10
10
|
include HasMockCallbackConnection
|
11
11
|
|
12
|
-
let(:
|
13
|
-
let(:
|
14
|
-
let(:translator) { Punchblock::Translator::Freeswitch.new connection }
|
15
|
-
let(:mock_call) { Punchblock::Translator::Freeswitch::Call.new 'foo', translator }
|
12
|
+
let(:translator) { Punchblock::Translator::Freeswitch.new connection }
|
13
|
+
let(:mock_call) { Punchblock::Translator::Freeswitch::Call.new 'foo', translator }
|
16
14
|
|
17
15
|
let :original_command do
|
18
16
|
Punchblock::Component::Output.new command_options
|
@@ -25,19 +23,19 @@ module Punchblock
|
|
25
23
|
end
|
26
24
|
|
27
25
|
let :command_options do
|
28
|
-
{ :render_document => {:value => ssml_doc} }
|
26
|
+
{ :render_document => {:value => ssml_doc}, :renderer => :flite }
|
29
27
|
end
|
30
28
|
|
31
29
|
def execute
|
32
|
-
subject.execute
|
30
|
+
subject.execute
|
33
31
|
end
|
34
32
|
|
35
33
|
subject { described_class.new original_command, mock_call }
|
36
34
|
|
37
35
|
describe '#execute' do
|
38
36
|
before { original_command.request! }
|
39
|
-
def expect_playback(voice =
|
40
|
-
subject.wrapped_object.should_receive(:application).once.with :speak, "#{
|
37
|
+
def expect_playback(voice = :kal, renderer = :flite)
|
38
|
+
subject.wrapped_object.should_receive(:application).once.with :speak, "#{renderer}|#{voice}|#{ssml_doc}"
|
41
39
|
end
|
42
40
|
|
43
41
|
let :ssml_doc do
|
@@ -6,10 +6,8 @@ module Punchblock
|
|
6
6
|
module Translator
|
7
7
|
describe Freeswitch do
|
8
8
|
let(:connection) { double 'Connection::Freeswitch' }
|
9
|
-
let(:media_engine) { :flite }
|
10
|
-
let(:default_voice) { :hal }
|
11
9
|
|
12
|
-
let(:translator) { described_class.new connection
|
10
|
+
let(:translator) { described_class.new connection }
|
13
11
|
let(:stream) { double 'RubyFS::Stream' }
|
14
12
|
|
15
13
|
before { connection.should_receive(:stream).at_most(:once).and_return stream }
|
@@ -248,8 +246,6 @@ module Punchblock
|
|
248
246
|
call.should be_a Freeswitch::Call
|
249
247
|
call.translator.should be subject
|
250
248
|
call.stream.should be stream
|
251
|
-
call.media_engine.should be media_engine
|
252
|
-
call.default_voice.should be default_voice
|
253
249
|
end
|
254
250
|
|
255
251
|
it 'should instruct the call to send a dial' do
|
@@ -430,8 +426,6 @@ module Punchblock
|
|
430
426
|
call.should be_a Freeswitch::Call
|
431
427
|
call.translator.should be subject
|
432
428
|
call.stream.should be stream
|
433
|
-
call.media_engine.should be media_engine
|
434
|
-
call.default_voice.should be default_voice
|
435
429
|
call.es_env.should be == {
|
436
430
|
:variable_direction => "inbound",
|
437
431
|
:variable_uuid => "3f0e1e18-c056-11e1-b099-fffeda3ce54f",
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: punchblock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Goecke
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-08-
|
13
|
+
date: 2013-08-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|