class SSDP::Consumer

Public Class Methods

new(options={}) click to toggle source
# File lib/ssdp/consumer.rb, line 6
def initialize(options={})
  @options = SSDP::DEFAULTS.merge options
  @search_socket = SSDP.create_broadcaster
  @watch = {
    :socket   => nil,
    :thread   => nil,
    :services => {}
  }
end

Public Instance Methods

start_watching_type(type, &block) click to toggle source
# File lib/ssdp/consumer.rb, line 33
def start_watching_type(type, &block)
  @watch[:services][type] = block
  start_watch if @watch[:thread].nil?
end
stop_watching_all() click to toggle source
# File lib/ssdp/consumer.rb, line 43
def stop_watching_all
  @watch[:services] = {}
  stop_watch if @watch[:thread]
end
stop_watching_type(type) click to toggle source
# File lib/ssdp/consumer.rb, line 38
def stop_watching_type(type)
  @watch[:services].delete type
  stop_watch if (@watch[:services].count == 0) && @watch[:thread]
end

Private Instance Methods

process_ssdp_packet(message, producer) click to toggle source
# File lib/ssdp/consumer.rb, line 139
def process_ssdp_packet(message, producer)
  ssdp = SSDP.parse_ssdp message
  { :address => producer[3], :port => producer[1] }.merge ssdp
end
search_async(options) click to toggle source
# File lib/ssdp/consumer.rb, line 73
def search_async(options)
  if options[:first_only]
    Thread.new { search_single options }
  else
    Thread.new { search_multi options }
  end
end
search_multi(options) click to toggle source
# File lib/ssdp/consumer.rb, line 113
def search_multi(options)
  remaining = options[:timeout]
  responses = []

  while remaining > 0
    start_time = Time.now
    ready = IO.select [@search_socket], nil, nil, remaining
    if ready
      message, producer = @search_socket.recvfrom options[:maxpack]
      if options[:filter].nil?
        responses << process_ssdp_packet(message, producer)
      else
        result = process_ssdp_packet message, producer
        responses << result if options[:filter].call(result)
      end
    end
    remaining -= (Time.now - start_time).to_i
  end

  if options[:synchronous]
    responses
  else
    options[:callback].call responses
  end
end
search_single(options) click to toggle source
# File lib/ssdp/consumer.rb, line 81
def search_single(options)
  result = nil
  found = false

  if options[:timeout]
    began = Time.now
    remaining = options[:timeout]
    while !found && remaining > 0
      ready = IO.select [@search_socket], nil, nil, remaining
      if ready
        message, producer = @search_socket.recvfrom options[:maxpack]
        result = process_ssdp_packet message, producer
        found = options[:filter].nil? ? true : options[:filter].call(result)
      end
      remaining = options[:timeout] - (Time.now - began).to_i
    end
  else
    until found
      message, producer = @search_socket.recvfrom options[:maxpack]
      result = process_ssdp_packet message, producer
      found = options[:filter].nil? ? true : options[:filter].call(result)
    end
  end

  result = nil unless found
  if options[:synchronous]
    result
  else
    options[:callback].call result
  end
end
search_sync(options) click to toggle source
# File lib/ssdp/consumer.rb, line 65
def search_sync(options)
  if options[:first_only]
    search_single options
  else
    search_multi options
  end
end
start_watch() click to toggle source
# File lib/ssdp/consumer.rb, line 144
def start_watch
  @watch[:socket] = SSDP.create_listener @options
  @watch[:thread] = Thread.new do
    begin
      loop do
        message, producer = @watch[:socket].recvfrom @options[:maxpack]
        notification = process_ssdp_packet message, producer
        notification_type = notification[:params]['NT']
        @watch[:services][notification_type].call notification if @watch[:services].include? notification_type
      end
    ensure
      @watch[:socket].close
    end
  end
end
stop_watch() click to toggle source
# File lib/ssdp/consumer.rb, line 160
def stop_watch
  @watch[:thread].exit
  @watch[:thread] = nil
end