librevox 0.1.1 → 0.2

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.
data/README.md CHANGED
@@ -37,8 +37,8 @@ techniques:
37
37
  require 'librevox'
38
38
 
39
39
  class MyInbound < Librevox::Listener::Inbound
40
- def on_event
41
- puts "Got event: #{event.content[:event_name]}"
40
+ def on_event e
41
+ puts "Got event: #{e.content[:event_name]}"
42
42
  end
43
43
 
44
44
  # You can add a hook for a certain event:
@@ -46,6 +46,12 @@ techniques:
46
46
  # It is instance_eval'ed, so you can use your instance methods etc:
47
47
  do_something
48
48
  end
49
+
50
+ # If your hook block takes an argument, a Librevox::Response object for
51
+ # the given event is passed on:
52
+ event :channel_bridge do |e|
53
+ ...
54
+ end
49
55
 
50
56
  def do_something
51
57
  ...
@@ -64,15 +70,17 @@ but it only receives events related to that given session.
64
70
  ### Dialplan
65
71
 
66
72
  When a call is made and Freeswitch connects to the outbound event listener,
67
- the `session` callback is executed. This is where you set up your dialplan:
73
+ `session_initiated` is called. This is where you set up your dialplan:
68
74
 
69
- session do
75
+ def session_initiated
70
76
  answer
71
77
  set "some_var", "some value"
72
78
  playback "path/to/file"
73
79
  hangup
74
80
  end
75
81
 
82
+ All channel variables are available as a hash named `session`.
83
+
76
84
  When using applications that expect a reply, such as `play_and_get_digits`,
77
85
  you have to use callbacks to read the value, as the function itself returns
78
86
  immediately due to the async nature of EventMachine:
data/TODO CHANGED
@@ -1,10 +1,17 @@
1
+ - inbound listener: only subscribe to events w/ hooks, unless `events :all`
2
+ specified
3
+
4
+ - map more commands/applications.
5
+
6
+ - check command/application input and raise ArgumentError, possibly.
7
+
8
+ - filter events
9
+
1
10
  - the execute_app/run_app business might be done better, simpler. e.g.
2
11
  having to pass the block for every command becomes a bit tedious.
3
12
 
4
13
  - move test suite from bacon -> test/unit.
5
14
 
6
- - map more commands/applications.
7
-
8
15
  - test how this works in async mode - I imagine that it might mess with
9
16
  @command_queue
10
17
 
@@ -12,13 +19,7 @@
12
19
  do e.g. originate("user/coltrane", :endpoint => bridge("user/davis")) and
13
20
  it would translate to "originate user/coltrane &bridge(user/davis)"
14
21
 
15
- - add logger.
16
-
17
- - check command/application input and raise ArgumentError.
18
-
19
22
  - maybe let commands handle the response, so something useful could be returned?
20
23
 
21
24
  - possibly catch all exceptions, so everything doesn't die? or should this be
22
25
  be the users responsibilty?
23
-
24
- - filter events
@@ -1,9 +1,27 @@
1
+ require 'logger'
1
2
  require 'eventmachine'
2
3
  require 'librevox/listener/inbound'
3
4
  require 'librevox/listener/outbound'
4
5
 
5
6
  module Librevox
6
- VERSION = "0.1.1"
7
+ VERSION = "0.2"
8
+
9
+ def self.options
10
+ @options ||= {
11
+ :log_file => STDOUT,
12
+ :log_level => Logger::INFO
13
+ }
14
+ end
15
+
16
+ def self.logger
17
+ @logger ||= logger!
18
+ end
19
+
20
+ def self.logger!
21
+ logger = Logger.new(options[:log_file])
22
+ logger.level = options[:log_level]
23
+ logger
24
+ end
7
25
 
8
26
  # When called without a block, it will start the listener that is passed as
9
27
  # first argument:
@@ -17,6 +35,7 @@ module Librevox
17
35
  # run OtherListner
18
36
  # end
19
37
  def self.start(klass=nil, args={}, &block)
38
+ logger.info "Starting Librevox"
20
39
  EM.run {
21
40
  block_given? ? instance_eval(&block) : run(klass, args)
22
41
  }
@@ -27,11 +46,9 @@ module Librevox
27
46
  port = args.delete(:port)
28
47
 
29
48
  if klass.ancestors.include? Librevox::Listener::Inbound
30
- port ||= "8021"
31
- EM.connect host, port, klass, args
49
+ EM.connect host, port || "8021", klass, args
32
50
  elsif klass.ancestors.include? Librevox::Listener::Outbound
33
- port ||= "8084"
34
- EM.start_server host, port, klass, args
51
+ EM.start_server host, port || "8084", klass, args
35
52
  end
36
53
  end
37
54
  end
@@ -8,10 +8,20 @@ module Librevox
8
8
  # Applications *must* pass on any eventual block passed to them.
9
9
  module Applications
10
10
  # Answers an incoming call or session.
11
- def answer(&b)
11
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_answer
12
+ def answer &b
12
13
  execute_app "answer", &b
13
14
  end
14
15
 
16
+ # Make an attended transfer
17
+ # @example
18
+ # att_xfer("user/davis")
19
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_att_xfer
20
+ # @todo Add support for origination_cancel_key
21
+ def att_xfer endpoint, &b
22
+ execute_app "att_xfer", endpoint, &b
23
+ end
24
+
15
25
  # Binds an application to the specified call legs.
16
26
  # @example
17
27
  # bind_meta_app :key => 2,
@@ -20,28 +30,98 @@ module Librevox
20
30
  # :application => "execute_extension",
21
31
  # :parameters => "dx XML features"
22
32
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_bind_meta_app
23
- def bind_meta_app(args={}, &b)
24
- key = args[:key]
25
- listen_to = args[:listen_to]
26
- respond_on = args[:respond_on]
27
- application = args[:application]
28
- parameters = args[:parameters] ? "::#{args[:parameters]}" : ""
29
-
30
- arg_string = "%s %s %s %s%s" % [key, listen_to, respond_on, application,
31
- parameters]
33
+ def bind_meta_app args={}, &b
34
+ arg_string =
35
+ args.values_at(:key, :listen_to, :respond_on, :application).join(" ")
36
+ arg_string += "::#{args[:parameters]}" if args[:parameters]
32
37
 
33
38
  execute_app "bind_meta_app", arg_string, &b
34
39
  end
35
40
 
36
- # Bridges an incoming call to an endpoint
41
+
42
+ # Bridges an incoming call to an endpoint, optionally taking an array of
43
+ # channel variables to set. If given an array of arrays, each contained
44
+ # array of endpoints will be called simultaneously, with the next array
45
+ # of endpoints as failover. See the examples below for different constructs
46
+ # and the callstring it sends to FreeSWITCH.
37
47
  # @example
38
48
  # bridge "user/coltrane", "user/backup-office"
49
+ # #=> user/coltrane,user/backup-office
50
+ # @example With channel variables
51
+ # bridge "user/coltrane", "user/backup-office", :some_var => "value"
52
+ # #=> {some_var=value}user/coltrane,user/backup-office
53
+ # @example With failover
54
+ # bridge ['user/coltrane', 'user/davis'], ['user/sun-ra', 'user/taylor']
55
+ # #=> user/coltrane,user/davis|user/sun-ra,user/taylor
39
56
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_bridgecall
40
- def bridge(*endpoints, &b)
41
- execute_app "bridge", endpoints.join(","), &b
57
+ def bridge *args, &b
58
+ variables = if args.last.is_a? Hash
59
+ # We need to sort the key/value pairs to facilitate testing.
60
+ # This can be removed once 1.8-compat is dropped.
61
+ key_value_pairs = args.pop.sort {|x,y| x.to_s <=> y.to_s}
62
+ key_value_pairs.map! {|k,v| "#{k}=#{v}"}
63
+ "{#{key_value_pairs.join(",")}}"
64
+ else
65
+ ""
66
+ end
67
+
68
+ endpoints = if args.first.is_a? Array
69
+ args.map {|e| e.join(",")}.join("|")
70
+ else
71
+ args.join ","
72
+ end
73
+
74
+ execute_app "bridge", variables + endpoints, &b
75
+ end
76
+
77
+ # Deflect a call by sending a REFER. Takes a SIP URI as argument, rerouting
78
+ # the call to that SIP URI.
79
+ #
80
+ # Beware that REFER only can be used on established calls. If a call hasn't
81
+ # been established with e.g. the {#answer} application, you should use
82
+ # {#redirect} instead.
83
+ # @example
84
+ # deflect "sip:miles@davis.com"
85
+ # @see #redirect
86
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_deflect
87
+ def deflect uri, &b
88
+ execute_app "deflect", uri, &b
89
+ end
90
+
91
+ # Exports a channel variable from the A leg to the B leg. Variables and
92
+ # their values will be replicated in any new channels created from the one
93
+ # export was called.
94
+ #
95
+ # Set :local => false if the variable should only be exported to the B-leg.
96
+ #
97
+ # @example
98
+ # export "some_var"
99
+ # @example Only export to B-leg
100
+ # export "some_var", :local => false
101
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_export
102
+ def export var, args={}, &b
103
+ nolocal = args[:local] == false ? "nolocal:" : "" # ugly!!111
104
+
105
+ execute_app "export", "#{nolocal}#{var}", &b
106
+ end
107
+
108
+ # Generate TGML tones
109
+ # @example Generate a 500ms beep at 800Hz
110
+ # gentones "%(500,0,800)"
111
+ # @example Generate a DTMF string
112
+ # gentones "0800500005"
113
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_gentones
114
+ def gentones tgml, &b
115
+ execute_app "gentones", tgml, &b
42
116
  end
43
117
 
44
- def hangup(cause="", &b)
118
+ # Hang up current channel
119
+ # @example
120
+ # hangup
121
+ # @example Hang up with a reason
122
+ # hangup "USER_BUSY"
123
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_hangup
124
+ def hangup cause="", &b
45
125
  execute_app "hangup", cause, &b
46
126
  end
47
127
 
@@ -55,7 +135,7 @@ module Librevox
55
135
  # :timeout => 5000,
56
136
  # :regexp => '\d+'
57
137
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_play_and_get_digits
58
- def play_and_get_digits(file, invalid_file, args={}, &b)
138
+ def play_and_get_digits file, invalid_file, args={}, &b
59
139
  min = args[:min] || 1
60
140
  max = args[:max] || 2
61
141
  tries = args[:tries] || 3
@@ -76,12 +156,20 @@ module Librevox
76
156
  # @example
77
157
  # playback "/path/to/file.wav"
78
158
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_playback
79
- def playback(file, &b)
159
+ def playback file, &b
80
160
  execute_app "playback", file, &b
81
161
  end
82
162
 
163
+ # Pre-answer establishes early media but does not answer.
164
+ # @example
165
+ # pre_anser
166
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_pre_answer
167
+ def pre_answer &b
168
+ execute_app "pre_answer", &b
169
+ end
170
+
83
171
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_read
84
- def read(file, args={}, &b)
172
+ def read file, args={}, &b
85
173
  min = args[:min] || 1
86
174
  max = args[:max] || 2
87
175
  terminators = args[:terminators] || "#"
@@ -103,16 +191,31 @@ module Librevox
103
191
  # @example With 20 second limit
104
192
  # record "/path/to/new/file.wac", :limit => 20
105
193
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_record
106
- def record(path, params={}, &b)
194
+ def record path, params={}, &b
107
195
  args = [path, params[:limit]].compact.join(" ")
108
196
  execute_app "record", args, &b
109
197
  end
110
198
 
199
+ # Redirect a channel to another endpoint. You must take care to not
200
+ # redirect incompatible channels, as that wont have the desired effect.
201
+ # I.e. if you redirect to a SIP URI, it should be a SIP channel.
202
+ #
203
+ # #{redirect} can only be used on non-established calls, i.e. calls that
204
+ # has not been answered with the #{answer} application yet. If the call has
205
+ # been answered, use #{deflect} instead.
206
+ # @example
207
+ # redirect "sip:freddie@hubbard.org"
208
+ # @see #{deflect}
209
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_redirect
210
+ def redirect uri, &b
211
+ execute_app "redirect", uri, &b
212
+ end
213
+
111
214
  # Sets a channel variable.
112
215
  # @example
113
216
  # set "some_var", "some value"
114
217
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_set
115
- def set(variable, value, &b)
218
+ def set variable, value, &b
116
219
  execute_app "set", "#{variable}=#{value}", &b
117
220
  end
118
221
 
@@ -120,8 +223,24 @@ module Librevox
120
223
  # @example
121
224
  # transfer "new_context"
122
225
  # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_transfer
123
- def transfer(context, &b)
226
+ def transfer context, &b
124
227
  execute_app "transfer", context, &b
125
228
  end
229
+
230
+ # Unbinds a previously bound key with bind_meta_app
231
+ # @example
232
+ # unbind_meta_app 3
233
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_unbind_meta_app
234
+ def unbind_meta_app key, &b
235
+ execute_app "unbind_meta_app", key.to_s, &b
236
+ end
237
+
238
+ # Unset a channel variable.
239
+ # @example
240
+ # unset "foo"
241
+ # @see http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_unset
242
+ def unset variable, &b
243
+ execute_app "unset", variable, &b
244
+ end
126
245
  end
127
246
  end
@@ -38,7 +38,7 @@ module Librevox
38
38
 
39
39
  def run_cmd(cmd, &block)
40
40
  send_data "#{cmd}\n\n"
41
- @api_queue << (block || lambda {})
41
+ @command_queue << (block || lambda {})
42
42
  end
43
43
 
44
44
  attr_accessor :response
@@ -46,33 +46,37 @@ module Librevox
46
46
 
47
47
  def post_init
48
48
  @command_delegate = CommandDelegate.new(self)
49
- @api_queue = []
49
+ @command_queue = []
50
50
  end
51
51
 
52
52
  def receive_request(header, content)
53
53
  @response = Librevox::Response.new(header, content)
54
54
 
55
55
  if response.event?
56
- on_event
57
- invoke_event response.event
58
- elsif response.api_response? && @api_queue.any?
59
- invoke_api_queue
56
+ on_event response.dup
57
+ invoke_event_hooks
58
+ elsif response.api_response? && @command_queue.any?
59
+ invoke_command_queue
60
60
  end
61
61
  end
62
62
 
63
63
  # override
64
- def on_event
64
+ def on_event(event)
65
65
  end
66
66
 
67
+ alias :done :close_connection_after_writing
68
+
67
69
  private
68
- def invoke_event(event_name)
69
- self.class.hooks.each do |name,block|
70
- instance_eval(&block) if name == event_name.downcase.to_sym
71
- end
70
+ def invoke_event_hooks
71
+ self.class.hooks.each {|name,block|
72
+ if name == response.event.downcase.to_sym
73
+ instance_exec response.dup, &block
74
+ end
75
+ }
72
76
  end
73
77
 
74
- def invoke_api_queue
75
- block = @api_queue.shift
78
+ def invoke_command_queue
79
+ block = @command_queue.shift
76
80
  block.call(response)
77
81
  end
78
82
  end
@@ -4,14 +4,6 @@ require 'librevox/applications'
4
4
  module Librevox
5
5
  module Listener
6
6
  class Outbound < Base
7
- class << self
8
- attr_reader :session_callback
9
-
10
- def session(&block)
11
- @session_callback = block
12
- end
13
- end
14
-
15
7
  include Librevox::Applications
16
8
 
17
9
  def execute_app(app, args="", params={}, &block)
@@ -25,10 +17,10 @@ module Librevox
25
17
  @read_channel_var = params[:read_var]
26
18
 
27
19
  if @read_channel_var
28
- @command_queue << lambda {update_session}
20
+ @application_queue << lambda {update_session}
29
21
  end
30
22
 
31
- @command_queue << (block || lambda {})
23
+ @application_queue << (block || lambda {})
32
24
  end
33
25
 
34
26
  # This should probably be in Application#sendmsg instead.
@@ -37,46 +29,47 @@ module Librevox
37
29
  end
38
30
 
39
31
  attr_accessor :session
32
+
33
+ # Called when a new session is initiated.
34
+ def session_initiated
35
+ end
40
36
 
41
37
  def post_init
42
38
  super
43
39
  @session = nil
44
- @command_queue = []
40
+ @application_queue = []
45
41
 
46
42
  send_data "connect\n\n"
47
43
  send_data "myevents\n\n"
48
- @command_queue << lambda {}
44
+ @application_queue << lambda {}
49
45
  send_data "linger\n\n"
50
- @command_queue << lambda {}
46
+ @application_queue << lambda {}
51
47
  end
52
48
 
53
49
  def receive_request(*args)
54
50
  super(*args)
55
51
 
56
52
  if session.nil?
57
- @session = response
58
- instance_eval &self.class.session_callback
53
+ @session = response.headers
54
+ session_initiated
59
55
  elsif response.event? && response.event == "CHANNEL_DATA"
60
- @session = response
56
+ @session = response.content
61
57
  resume_with_channel_var
62
58
  elsif response.command_reply? && !response.event?
63
- @command_queue.shift.call if @command_queue.any?
59
+ @application_queue.shift.call if @application_queue.any?
64
60
  end
65
61
  end
66
62
 
67
63
  def resume_with_channel_var
68
64
  if @read_channel_var
69
65
  variable = "variable_#{@read_channel_var}".to_sym
70
- value = @session.content[variable]
71
- @command_queue.shift.call(value) if @command_queue.any?
66
+ value = @session[variable]
67
+ @application_queue.shift.call(value) if @application_queue.any?
72
68
  end
73
69
  end
74
70
 
75
71
  def update_session
76
- send_data("api uuid_dump #{session.headers[:unique_id]}\n\n")
77
- end
78
-
79
- def session_initiated
72
+ send_data("api uuid_dump #{session[:unique_id]}\n\n")
80
73
  end
81
74
  end
82
75
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "librevox"
3
- s.version = "0.1.1"
4
- s.date = "2010-01-05"
3
+ s.version = "0.2"
4
+ s.date = "2010-01-26"
5
5
  s.summary = "Ruby library for interacting with FreeSWITCH."
6
6
  s.email = "harry@vangberg.name"
7
7
  s.homepage = "http://github.com/ichverstehe/librevox"
@@ -25,13 +25,18 @@ shared "events" do
25
25
 
26
26
  @class.event(:some_event) {send_data "something"}
27
27
  @class.event(:other_event) {send_data "something else"}
28
+ @class.event(:hook_with_arg) {|e| send_data "got event arg: #{e.object_id}"}
29
+
30
+ def @listener.on_event(e)
31
+ send_data "from on_event: #{e.object_id}"
32
+ end
28
33
 
29
34
  # Establish session
30
35
  @listener.receive_data("Content-Length: 0\nTest: Testing\n\n")
31
36
  end
32
37
 
33
38
  should "add event hook" do
34
- @class.hooks.size.should == 2
39
+ @class.hooks.size.should == 3
35
40
  end
36
41
 
37
42
  should "execute callback for event" do
@@ -42,11 +47,28 @@ shared "events" do
42
47
  @listener.read_data.should == "something"
43
48
  end
44
49
 
50
+ should "pass response duplicate as arg to hook block" do
51
+ @listener.receive_data("Content-Length: 25\n\nEvent-Name: HOOK_WITH_ARG\n\n")
52
+ reply = @listener.read_data
53
+ reply.should =~ /^got event arg: /
54
+ reply.should.not =~ /^got event arg: #{@listener.response.object_id}$/
55
+ end
56
+
45
57
  should "expose response as event" do
46
58
  @listener.receive_data("Content-Length: 23\n\nEvent-Name: OTHER_EVENT\n\n")
47
59
  @listener.event.class.should == Librevox::Response
48
60
  @listener.event.content[:event_name].should == "OTHER_EVENT"
49
61
  end
62
+
63
+ should "call on_event" do
64
+ @listener.receive_data("Content-Length: 23\n\nEvent-Name: THIRD_EVENT\n\n")
65
+ @listener.read_data.should =~ /^from on_event/
66
+ end
67
+
68
+ should "call on_event with response duplicate as argument" do
69
+ @listener.receive_data("Content-Length: 23\n\nEvent-Name: THIRD_EVENT\n\n")
70
+ @listener.read_data.should.not =~ /^from on_event: #{@listener.response.object_id}$/
71
+ end
50
72
  end
51
73
 
52
74
  module Librevox::Commands
@@ -66,6 +88,9 @@ shared "api commands" do
66
88
  describe "multiple api commands" do
67
89
  before do
68
90
  @listener.outgoing_data.clear
91
+
92
+ def @listener.on_event(e) end # Don't send anything, kthx.
93
+
69
94
  @class.event(:api_test) {
70
95
  api :sample_cmd, "foo" do
71
96
  api :sample_cmd, "foo", "bar baz"
@@ -10,7 +10,7 @@ module Librevox::Applications
10
10
  end
11
11
 
12
12
  class OutboundTestListener < Librevox::Listener::Outbound
13
- session do
13
+ def session_initiated
14
14
  send_data "session was initiated"
15
15
  end
16
16
  end
@@ -34,7 +34,7 @@ describe "Outbound listener" do
34
34
  end
35
35
 
36
36
  should "establish a session" do
37
- @listener.session.class.should.equal Librevox::Response
37
+ @listener.session.class.should.equal Hash
38
38
  end
39
39
 
40
40
  should "call session callback after establishing new session" do
@@ -42,7 +42,7 @@ describe "Outbound listener" do
42
42
  end
43
43
 
44
44
  should "make channel variables available through session" do
45
- @listener.session.headers[:caller_caller_id_number].should.equal "8675309"
45
+ @listener.session[:caller_caller_id_number].should.equal "8675309"
46
46
  end
47
47
 
48
48
  behaves_like "events"
@@ -54,7 +54,7 @@ describe "Outbound listener" do
54
54
  end
55
55
 
56
56
  class OutboundListenerWithNestedApps < Librevox::Listener::Outbound
57
- session do
57
+ def session_initiated
58
58
  sample_app "foo" do
59
59
  sample_app "bar"
60
60
  end
@@ -106,7 +106,7 @@ module Librevox::Applications
106
106
  end
107
107
 
108
108
  class OutboundListenerWithReader < Librevox::Listener::Outbound
109
- session do
109
+ def session_initiated
110
110
  reader_app do |data|
111
111
  send_data "read this: #{data}"
112
112
  end
@@ -136,7 +136,7 @@ describe "Outbound listener with app reading data" do
136
136
  should "update session with new data" do
137
137
  @listener.receive_data("Content-Type: command/reply\nContent-Length: 3\n\n+OK\n\n")
138
138
  @listener.receive_data("Content-Type: command/reply\nContent-Length: 44\n\nEvent-Name: CHANNEL_DATA\nSession-Var: Second\n\n")
139
- @listener.session.content[:session_var].should == "Second"
139
+ @listener.session[:session_var].should == "Second"
140
140
  end
141
141
 
142
142
  should "pass value of channel variable to block" do
@@ -148,7 +148,7 @@ end
148
148
 
149
149
  class OutboundListenerWithNonNestedApps < Librevox::Listener::Outbound
150
150
  attr_reader :queue
151
- session do
151
+ def session_initiated
152
152
  sample_app "foo"
153
153
  reader_app do |data|
154
154
  send_data "the end: #{data}"
@@ -190,7 +190,7 @@ module Librevox::Commands
190
190
  end
191
191
 
192
192
  class OutboundListenerWithAppsAndApi < Librevox::Listener::Outbound
193
- session do
193
+ def session_initiated
194
194
  sample_app "foo" do
195
195
  api :sample_cmd, "bar" do
196
196
  sample_app "baz"
@@ -1,7 +1,7 @@
1
1
  require 'spec/helper'
2
2
  require 'librevox/applications'
3
3
 
4
- module ApplicationTest
4
+ module AppTest
5
5
  include Librevox::Applications
6
6
 
7
7
  extend self
@@ -17,16 +17,24 @@ module ApplicationTest
17
17
  end
18
18
 
19
19
  describe Librevox::Applications do
20
- A = ApplicationTest
20
+ describe "answer" do
21
+ should "answer" do
22
+ app = AppTest.answer
23
+ app[:name].should == "answer"
24
+ end
25
+ end
21
26
 
22
- should "answer" do
23
- app = A.answer
24
- app[:name].should == "answer"
27
+ describe "att_xfer" do
28
+ should "transfer to endpoint" do
29
+ app = AppTest.att_xfer("user/davis")
30
+ app[:name].should == "att_xfer"
31
+ app[:args].should == "user/davis"
32
+ end
25
33
  end
26
34
 
27
35
  describe "bind_meta_app" do
28
36
  should "bind meta app" do
29
- app = A.bind_meta_app :key => "2",
37
+ app = AppTest.bind_meta_app :key => "2",
30
38
  :listen_to => :a,
31
39
  :respond_on => :s,
32
40
  :application => "hangup"
@@ -36,7 +44,7 @@ describe Librevox::Applications do
36
44
  end
37
45
 
38
46
  should "bind meta app with parameters" do
39
- app = A.bind_meta_app :key => "2",
47
+ app = AppTest.bind_meta_app :key => "2",
40
48
  :listen_to => :a,
41
49
  :respond_on => :s,
42
50
  :application => "execute_extension",
@@ -47,33 +55,85 @@ describe Librevox::Applications do
47
55
  end
48
56
  end
49
57
 
50
- should "bridge" do
51
- app = A.bridge('user/coltrane')
52
- app[:name].should == "bridge"
53
- app[:args].should == 'user/coltrane'
58
+ describe "bridge" do
59
+ should "bridge to endpoints" do
60
+ app = AppTest.bridge('user/coltrane')
61
+ app[:name].should == "bridge"
62
+ app[:args].should == 'user/coltrane'
63
+
64
+ app = AppTest.bridge('user/coltrane', 'user/davis')
65
+ app[:args].should == 'user/coltrane,user/davis'
66
+ end
67
+
68
+ should "bridge with variables" do
69
+ app = AppTest.bridge('user/coltrane', 'user/davis', :foo => 'bar', :lol => 'cat')
70
+ app[:name].should == "bridge"
71
+
72
+ # fragile. hashes are not ordered in ruby 1.8
73
+ app[:args].should == "{foo=bar,lol=cat}user/coltrane,user/davis"
74
+ end
75
+
76
+ should "bridge with failover" do
77
+ app = AppTest.bridge(
78
+ ['user/coltrane', 'user/davis'], ['user/sun-ra', 'user/taylor']
79
+ )
80
+
81
+ app[:name].should == "bridge"
82
+ app[:args].should == "user/coltrane,user/davis|user/sun-ra,user/taylor"
83
+ end
84
+
85
+ # should "bridge with per endpoint variables" do
86
+ # end
87
+ end
88
+
89
+ describe "deflect" do
90
+ should "deflect call" do
91
+ app = AppTest.deflect "sip:miles@davis.org"
92
+ app[:name].should == "deflect"
93
+ app[:args].should == "sip:miles@davis.org"
94
+ end
95
+ end
96
+
97
+ describe "export" do
98
+ should "export variable" do
99
+ app = AppTest.export 'some_var'
100
+ app[:name].should == "export"
101
+ app[:args].should == "some_var"
102
+ end
54
103
 
55
- app = A.bridge('user/coltrane', 'user/davis')
56
- app[:args].should == 'user/coltrane,user/davis'
104
+ should "only export to b-leg " do
105
+ app = AppTest.export 'some_var', :local => false
106
+ app[:name].should == "export"
107
+ app[:args].should == "nolocal:some_var"
108
+ end
109
+ end
110
+
111
+ describe "gentones" do
112
+ should "generate tones" do
113
+ app = AppTest.gentones("%(500,0,800)")
114
+ app[:name].should == "gentones"
115
+ app[:args].should == "%(500,0,800)"
116
+ end
57
117
  end
58
118
 
59
119
  should "hangup" do
60
- app = A.hangup
120
+ app = AppTest.hangup
61
121
  app[:name].should == "hangup"
62
122
 
63
- app = A.hangup("some cause")
123
+ app = AppTest.hangup("some cause")
64
124
  app[:args].should == "some cause"
65
125
  end
66
126
 
67
127
  describe "play_and_get_digits" do
68
128
  should "have defaults" do
69
- app = A.play_and_get_digits "please-enter", "wrong-try-again"
129
+ app = AppTest.play_and_get_digits "please-enter", "wrong-try-again"
70
130
  app[:name].should == "play_and_get_digits"
71
131
  app[:args].should == "1 2 3 5000 # please-enter wrong-try-again read_digits_var \\d+"
72
132
  app[:params][:read_var].should == "read_digits_var"
73
133
  end
74
134
 
75
135
  should "take params" do
76
- app = A.play_and_get_digits "please-enter", "invalid-choice",
136
+ app = AppTest.play_and_get_digits "please-enter", "invalid-choice",
77
137
  :min => 2,
78
138
  :max => 3,
79
139
  :tries => 4,
@@ -88,21 +148,28 @@ describe Librevox::Applications do
88
148
  end
89
149
 
90
150
  should "playback" do
91
- app = A.playback("uri://some/file.wav")
151
+ app = AppTest.playback("uri://some/file.wav")
92
152
  app[:name].should == "playback"
93
153
  app[:args].should == "uri://some/file.wav"
94
154
  end
95
155
 
156
+ describe "pre_answer" do
157
+ should "pre_answer" do
158
+ app = AppTest.pre_answer
159
+ app[:name].should == "pre_answer"
160
+ end
161
+ end
162
+
96
163
  describe "read" do
97
164
  should "read with defaults" do
98
- app = A.read "please-enter.wav"
165
+ app = AppTest.read "please-enter.wav"
99
166
  app[:name].should == "read"
100
167
  app[:args].should == "1 2 please-enter.wav read_digits_var 5000 #"
101
168
  app[:params][:read_var].should == "read_digits_var"
102
169
  end
103
170
 
104
171
  should "take params" do
105
- app = A.read "please-enter.wav",
172
+ app = AppTest.read "please-enter.wav",
106
173
  :min => 2,
107
174
  :max => 3,
108
175
  :terminators => "0",
@@ -116,27 +183,51 @@ describe Librevox::Applications do
116
183
 
117
184
  describe "record" do
118
185
  should "start recording" do
119
- app = A.record "/path/to/file.mp3"
186
+ app = AppTest.record "/path/to/file.mp3"
120
187
  app[:name].should == "record"
121
188
  app[:args].should == "/path/to/file.mp3"
122
189
  end
123
190
 
124
191
  should "start recording with time limit" do
125
- app = A.record "/path/to/file.mp3", :limit => 15
192
+ app = AppTest.record "/path/to/file.mp3", :limit => 15
126
193
  app[:name].should == "record"
127
194
  app[:args].should == "/path/to/file.mp3 15"
128
195
  end
129
196
  end
130
197
 
198
+ describe "redirect" do
199
+ should "redirect to URI" do
200
+ app = AppTest.redirect("sip:miles@davis.org")
201
+ app[:name].should == "redirect"
202
+ app[:args].should == "sip:miles@davis.org"
203
+ end
204
+ end
205
+
131
206
  should "set" do
132
- app = A.set("foo", "bar")
207
+ app = AppTest.set("foo", "bar")
133
208
  app[:name].should == "set"
134
209
  app[:args].should == "foo=bar"
135
210
  end
136
211
 
137
212
  should "transfer" do
138
- app = A.transfer "new_extension"
213
+ app = AppTest.transfer "new_extension"
139
214
  app[:name].should == "transfer"
140
215
  app[:args].should == "new_extension"
141
216
  end
217
+
218
+ describe "unbind_meta_app" do
219
+ should "unbind" do
220
+ app = AppTest.unbind_meta_app 3
221
+ app[:name].should == "unbind_meta_app"
222
+ app[:args].should == "3"
223
+ end
224
+ end
225
+
226
+ describe "unset" do
227
+ should "unset a variable" do
228
+ app = AppTest.unset('foo')
229
+ app[:name].should == "unset"
230
+ app[:args].should == "foo"
231
+ end
232
+ end
142
233
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: librevox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: "0.2"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Vangberg
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-05 00:00:00 +01:00
12
+ date: 2010-01-26 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15