lib/adhearsion/call_controller/dial.rb in adhearsion-2.0.0.beta1 vs lib/adhearsion/call_controller/dial.rb in adhearsion-2.0.0.rc1

- old
+ new

@@ -1,17 +1,23 @@ +# encoding: utf-8 + module Adhearsion class CallController module Dial # # Dial a third party and join to this call # - # @param [String|Array<String>] number represents the extension or "number" that asterisk should dial. + # @param [String|Array<String>|Hash] number represents the extension or "number" that asterisk should dial. # Be careful to not just specify a number like 5001, 9095551001 # You must specify a properly formatted string as Asterisk would expect to use in order to understand # whether the call should be dialed using SIP, IAX, or some other means. # You can also specify an array of destinations: each will be called with the same options simultaneously. # The first call answered is joined, the others are hung up. + # A hash argument has the dial target as each key, and an hash of options as the value, in the form: + # dial({'SIP/100' => {:timeout => 3000}, 'SIP/200' => {:timeout => 4000} }) + # The option hash for each target is merged into the global options, overriding them for the single dial. + # Destinations are dialed simultaneously as with an array. # # @param [Hash] options # # +:from+ - the caller id to be used when the call is placed. It is advised you properly adhere to the # policy of VoIP termination providers with respect to caller id values. @@ -29,11 +35,12 @@ # # @example Make a call using the IAX provider to the PSTN # dial "IAX2/my.id@voipjet/19095551234", :from => "John Doe <9095551234>" # def dial(to, options = {}, latch = nil) - targets = Array(to) + targets = to.respond_to?(:has_key?) ? to : Array(to) + status = DialStatus.new latch ||= CountDownLatch.new targets.size call.on_end { |_| latch.countdown! until latch.count == 0 } @@ -41,56 +48,61 @@ _for = options.delete :for options[:timeout] ||= _for if _for options[:from] ||= call.from - calls = targets.map do |target| + calls = targets.map do |target, specific_options| new_call = OutboundCall.new new_call.on_answer do |event| - calls.each do |call_to_hangup, target| + calls.each do |call_to_hangup, _| begin next if call_to_hangup.id == new_call.id - logger.debug "Hanging up call #{call_to_hangup.id} because it was not the first to answer a #dial" + logger.debug "#dial hanging up call #{call_to_hangup.id} because this call has been answered by another channel" call_to_hangup.hangup rescue Celluloid::DeadActorError # This actor may previously have been shut down due to the call ending end end - new_call.register_event_handler Punchblock::Event::Unjoined, :other_call_id => call.id do |event| + new_call.register_event_handler Punchblock::Event::Unjoined, :other_call_id => call.id do |unjoined| new_call["dial_countdown_#{call.id}"] = true latch.countdown! throw :pass end - logger.debug "Joining call #{new_call.id} to #{call.id} due to a #dial" + logger.debug "#dial joining call #{new_call.id} to #{call.id}" new_call.join call status.answer! end new_call.on_end do |event| latch.countdown! unless new_call["dial_countdown_#{call.id}"] + + case event.reason + when :error + status.error! + end end - [new_call, target] + [new_call, target, specific_options] end - calls.map! do |call, target| - call.dial target, options + calls.map! do |call, target, specific_options| + local_options = options.dup.deep_merge specific_options if specific_options + call.dial target, (local_options || options) call end status.calls = calls no_timeout = latch.wait options[:timeout] status.timeout! unless no_timeout - logger.debug "#dial finished. Hanging up #{calls.size} outbound calls #{calls.inspect}." + logger.debug "#dial finished. Hanging up #{calls.size} outbound calls: #{calls.map(&:id).join ", "}." calls.each do |outbound_call| begin - logger.debug "Hanging up #{outbound_call} because the #dial that created it is complete." outbound_call.hangup rescue Celluloid::DeadActorError # This actor may previously have been shut down due to the call ending end end @@ -98,21 +110,28 @@ status end class DialStatus attr_accessor :calls - attr_reader :result def initialize - @result = :no_answer + @result = nil end + def result + @result || :no_answer + end + def answer! @result = :answer end def timeout! - @result = :timeout + @result ||= :timeout + end + + def error! + @result ||= :error end end end#module Dial end