class Punchblock::Translator::Freeswitch::Call

Constants

HANGUP_CAUSE_TO_END_REASON
REJECT_TO_HANGUP_REASON

Attributes

direction[R]
es_env[R]
id[R]
stream[R]
translator[R]

Public Class Methods

new(id, translator, es_env = nil, stream = nil) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 44
def initialize(id, translator, es_env = nil, stream = nil)
  @id, @translator, @stream = id, translator, stream
  @es_env = es_env || {}
  @components = {}
  @pending_joins, @pending_unjoins = {}, {}
  @answered = false
  setup_handlers
end

Public Instance Methods

actor_died(actor, reason) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 234
def actor_died(actor, reason)
  return unless reason
  pb_logger.error "A linked actor (#{actor.inspect}) died due to #{reason.inspect}"
  if id = @components.key(actor)
    @components.delete id
    complete_event = Punchblock::Event::Complete.new :component_id => id, source_uri: id, :reason => Punchblock::Event::Complete::Error.new
    send_pb_event complete_event
  end
end
answered?() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 169
def answered?
  @answered
end
application(*args) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 119
def application(*args)
  stream.application id, *args
end
component_with_id(component_id) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 57
def component_with_id(component_id)
  @components[component_id]
end
dial(dial_command) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 131
def dial(dial_command)
  @direction = :outbound

  cid_number, cid_name = dial_command.from, nil
  if dial_command.from
    dial_command.from.match(/(?<cid_name>.*)<(?<cid_number>.*)>/) do |m|
      cid_name = m[:cid_name].strip
      cid_number = m[:cid_number]
    end
  end

  options = {
    :return_ring_ready  => true,
    :origination_uuid   => id
  }
  options[:origination_caller_id_number] = "'#{cid_number}'" if cid_number.present?
  options[:origination_caller_id_name] = "'#{cid_name}'" if cid_name.present?
  options[:originate_timeout] = dial_command.timeout/1000 if dial_command.timeout
  dial_command.headers.each do |name, value|
    options["sip_h_#{name}"] = "'#{value}'"
  end
  opts = options.inject([]) do |a, (k, v)|
    a << "#{k}=#{v}"
  end.join(',')

  stream.bgapi "originate {#{opts}}#{dial_command.to} &park()"

  dial_command.response = Ref.new uri: id
end
execute_command(command) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 173
def execute_command(command)
  if command.component_id
    if component = component_with_id(command.component_id)
      component.execute_command command
    else
      command.response = ProtocolError.new.setup :item_not_found, "Could not find a component with ID #{command.component_id} for call #{id}", id, command.component_id
    end
  end
  case command
  when Command::Accept
    application 'respond', '180 Ringing'
    command.response = true
  when Command::Answer
    if answered?
      command.response = true
    else
      command_id = Punchblock.new_uuid
      register_tmp_handler :es, :event_name => 'CHANNEL_ANSWER', [:[], :scope_variable_punchblock_command_id] => command_id do
        command.response = true
      end
      application 'answer', "%[punchblock_command_id=#{command_id}]"
    end
  when Command::Hangup
    hangup
    command.response = true
  when Command::Join
    @pending_joins[command.call_uri] = command
    uuid_foo :bridge, command.call_uri
  when Command::Unjoin
    @pending_unjoins[command.call_uri] = command
    uuid_foo :transfer, '-both park inline'
  when Command::Reject
    hangup REJECT_TO_HANGUP_REASON[command.reason]
    command.response = true
  when Punchblock::Component::Output
    media_renderer = command.renderer || :freeswitch
    case media_renderer.to_s
    when 'freeswitch', 'native'
      execute_component Component::Output, command
    when 'flite'
      execute_component Component::FliteOutput, command
    else
      execute_component Component::TTSOutput, command
    end
  when Punchblock::Component::Input
    execute_component Component::Input, command
  when Punchblock::Component::Record
    execute_component Component::Record, command
  else
    command.response = ProtocolError.new.setup 'command-not-acceptable', "Did not understand command for call #{id}", id
  end
end
handle_es_event(event) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 115
def handle_es_event(event)
  trigger_handler :es, event
end
hangup(reason = 'MANAGER_REQUEST') click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 226
def hangup(reason = 'MANAGER_REQUEST')
  sendmsg :call_command => 'hangup', :hangup_cause => reason
end
inbound?() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 165
def inbound?
  direction == :inbound
end
inspect()
Alias for: to_s
logger_id() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 230
def logger_id
  "#{self.class}: #{id}"
end
outbound?() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 161
def outbound?
  direction == :outbound
end
register_component(component) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 53
def register_component(component)
  @components[component.id] ||= component
end
send_offer() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 61
def send_offer
  @direction = :inbound
  send_pb_event offer_event
end
sendmsg(*args) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 123
def sendmsg(*args)
  stream.sendmsg id, *args
end
setup_handlers() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 71
def setup_handlers
  register_handler :es, :event_name => 'CHANNEL_ANSWER' do
    @answered = true
    send_pb_event Event::Answered.new
    throw :pass
  end

  register_handler :es, :event_name => 'CHANNEL_STATE', [:[], :channel_call_state] => 'RINGING' do
    send_pb_event Event::Ringing.new
  end

  register_handler :es, :event_name => 'CHANNEL_HANGUP' do |event|
    @components.dup.each_pair do |id, component|
      safe_from_dead_actors do
        component.call_ended if component.alive?
      end
    end
    send_end_event HANGUP_CAUSE_TO_END_REASON[event[:hangup_cause]]
  end

  register_handler :es, :event_name => 'CHANNEL_BRIDGE' do |event|
    command = @pending_joins[event[:other_leg_unique_id]]
    command.response = true if command

    other_call_uri = event[:unique_id] == id ? event[:other_leg_unique_id] : event[:unique_id]
    send_pb_event Event::Joined.new(:call_uri => other_call_uri)
  end

  register_handler :es, :event_name => 'CHANNEL_UNBRIDGE' do |event|
    command = @pending_unjoins[event[:other_leg_unique_id]]
    command.response = true if command

    other_call_uri = event[:unique_id] == id ? event[:other_leg_unique_id] : event[:unique_id]
    send_pb_event Event::Unjoined.new(:call_uri => other_call_uri)
  end

  register_handler :es, [:has_key?, :scope_variable_punchblock_component_id] => true do |event|
    if component = component_with_id(event[:scope_variable_punchblock_component_id])
      safe_from_dead_actors { component.handle_es_event event if component.alive? }
    end
    throw :pass
  end
end
to_s() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 66
def to_s
  "#<#{self.class}:#{id}>"
end
Also aliased as: inspect
uuid_foo(app, args = '') click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 127
def uuid_foo(app, args = '')
  stream.bgapi "uuid_#{app} #{id} #{args}"
end

Private Instance Methods

execute_component(type, command, *execute_args) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 252
def execute_component(type, command, *execute_args)
  type.new_link(command, current_actor).tap do |component|
    register_component component
    component.execute(*execute_args)
  end
end
headers() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 270
def headers
  es_env.to_a.inject({}) do |accumulator, element|
    accumulator['X-' + element[0].to_s] = element[1] || ''
    accumulator
  end
end
offer_event() click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 264
def offer_event
  Event::Offer.new :to      => es_env[:variable_sip_to_uri],
                   :from    => "#{es_env[:variable_effective_caller_id_name]} <#{es_env[:variable_sip_from_uri]}>",
                   :headers => headers
end
send_end_event(reason) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 246
def send_end_event(reason)
  send_pb_event Event::End.new(:reason => reason)
  translator.deregister_call id
  terminate
end
send_pb_event(event) click to toggle source
# File lib/punchblock/translator/freeswitch/call.rb, line 259
def send_pb_event(event)
  event.target_call_id = id
  translator.handle_pb_event event
end