punchblock 2.0.0.beta1 → 2.0.0.beta2
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.
- 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
|