Repository URL to install this package:
Version:
0.6 ▾
|
require 'ffi'
require 'ipaddr'
module FFI # :nodoc:
module HDHomeRun
extend FFI::Library
ffi_lib ['hdhomerun', 'libhdhomerun.so.1']
VIDEO_DATA_BUFFER_SIZE_1S = (20000000 / 8)
DEVICE_TYPE_TUNER = 0x00000001
DEVICE_ID_WILDCARD = 0xFFFFFFFF
attach_function :create_from_str,
:hdhomerun_device_create_from_str,
[:string, :pointer],
:pointer
attach_function :get_device_id_requested,
:hdhomerun_device_get_device_id_requested,
[:pointer],
:uint
attach_function :validate_device_id,
:hdhomerun_discover_validate_device_id,
[:uint],
:int
attach_function :get_model_str,
:hdhomerun_device_get_model_str,
[:pointer],
:string
attach_function :get_var,
:hdhomerun_device_get_var,
[:pointer, :string, :pointer, :pointer],
:int
attach_function :set_var,
:hdhomerun_device_set_var,
[:pointer, :string, :string, :pointer, :pointer],
:int
attach_function :set_tuner_from_str,
:hdhomerun_device_set_tuner_from_str,
[:pointer, :string],
:int
attach_function :stream_start,
:hdhomerun_device_stream_start,
[:pointer],
:int
attach_function :stream_stop,
:hdhomerun_device_stream_stop,
[:pointer],
:void
attach_function :stream_recv,
:hdhomerun_device_stream_recv,
[:pointer, :ulong, :pointer],
:pointer
attach_function :get_video_stats,
:hdhomerun_device_get_video_stats,
[:pointer, :pointer],
:void
attach_function :discover_find_devices_custom,
:hdhomerun_discover_find_devices_custom,
[ :uint32, :uint32, :uint32, :pointer, :int ],
:int
attach_function :lockkey_use_value,
:hdhomerun_device_tuner_lockkey_use_value,
[:pointer, :ulong],
:void
attach_function :destroy,
:hdhomerun_device_destroy,
[:pointer],
:void
attach_function :lock,
:hdhomerun_device_tuner_lockkey_request,
[:pointer, :string],
:int
attach_function :set_tuner_target,
:hdhomerun_device_set_tuner_target,
[:pointer, :pointer],
:int
attach_function :get_tuner_channelmap,
:hdhomerun_device_get_tuner_channelmap,
[:pointer, :pointer],
:int
attach_function :get_channelmap_scan_group,
:hdhomerun_channelmap_get_channelmap_scan_group,
[:pointer],
:string
attach_function :channelscan_init,
:hdhomerun_device_channelscan_init,
[:pointer, :pointer],
:int
attach_function :channelscan_advance,
:hdhomerun_device_channelscan_advance,
[:pointer, :pointer],
:int
attach_function :channelscan_detect,
:hdhomerun_device_channelscan_detect,
[:pointer, :pointer],
:int
attach_function :unlock,
:hdhomerun_device_tuner_lockkey_release,
[:pointer],
:int
attach_function :get_tuner_status,
:hdhomerun_device_get_tuner_status,
[:pointer, :pointer, :pointer],
:int
attach_function :get_tuner_streaminfo,
:hdhomerun_device_get_tuner_streaminfo,
[:pointer, :pointer],
:int
attach_function :get_tuner_program,
:hdhomerun_device_get_tuner_program,
[:pointer, :pointer],
:int
attach_function :set_tuner_program,
:hdhomerun_device_set_tuner_program,
[:pointer, :string],
:int
attach_function :channel_list_create,
:hdhomerun_channel_list_create,
[:string],
:pointer
attach_function :channel_list_first,
:hdhomerun_channel_list_first,
[:pointer],
:pointer
attach_function :channel_list_last,
:hdhomerun_channel_list_last,
[:pointer],
:pointer
attach_function :channel_list_next,
:hdhomerun_channel_list_next,
[:pointer, :pointer],
:pointer
attach_function :channel_list_prev,
:hdhomerun_channel_list_prev,
[:pointer, :pointer],
:pointer
class ChannelEntry < FFI::Struct
layout :next, :pointer,
:prev, :pointer,
:frequency, :uint32,
:channel_number, :uint16,
:name, [:char, 16]
def to_s
"#{frequency} #{channel_number} #{name}"
end
%w{frequency channel_number name}.each do |name|
define_method name do
send(:[], name.to_sym)
end
end
end
class ChannelList < FFI::Struct
layout :head, :pointer,
:tail, :pointer
end
##
# HDHomeRun status for channel scan
#
# Has the following fields:
# * +channel+
# * +modulation_type+
# * +signal_strength+
# * +signal_to_noise+
# * +symbol_error_rate+
# * +bits_per_second+
# * +packets_per_second+
class Status < FFI::Struct
layout :channel, [:char, 32],
:modulation_type, [:char, 32],
:signal_present, :int,
:lock_supported, :int,
:lock_unsupported, :int,
:signal_strength, :uint,
:signal_to_noise, :uint,
:symbol_error_rate, :uint,
:bits_per_second, :uint32,
:packets_per_second, :uint32
def to_s
"LOCK: #{modulation_type} (ss=#{signal_strength} snq=#{signal_to_noise} seq=#{symbol_error_rate})"
end
%w{modulation_type signal_strength signal_to_noise symbol_error_rate bits_per_second packets_per_second}.each do |name|
define_method name do
send(:[], name.to_sym)
end
end
##
# Is there a signal present?
def signal?
return self[:signal_present] == 1
end
end
class Program < FFI::Struct
layout :string, [:char, 64],
:number, :uint16,
:major, :uint16,
:minor, :uint16,
:type, :uint16,
:name, [:char, 32]
def to_s
"PROGRAM #{string}"
end
%w{number major minor type}.each do |name|
define_method name do
send(:[], name.to_sym)
end
end
def string
self[:string].to_s
end
def name
self[:name].to_s
end
end
##
# HDHomeRun result object.
#
# Contains information about a channel scan result.
class Result < FFI::Struct
layout :channel_string, [:char, 64],
:channel_map, :uint32,
:frequency, :uint32,
:status, HDHomeRun::Status,
:program_count, :int,
:programs, [HDHomeRun::Program, 64],
:tsid_detected, :int,
:tsid, :uint16
%w{frequency program_count status}.each do |name|
define_method name do
send(:[], name.to_sym)
end
end
def to_s
output = "SCANNING: #{self[:frequency]} (#{self[:channel_string]})"
output += "\n#{self[:status]}"
output += "\nTSID: #{tsid}" if tsid?
programs.each do |program|
output += "\n#{program.to_s}"
end
output
end
def set_channel
@channel_string = self[:channel_string]
(@broadcast_standard, @channel) = @channel_string.to_s.split ':'
end
def channel
set_channel() if @channel_string.nil?
@channel
end
def standard
set_channel() if @channel_string.nil?
@broadcast_standard
end
def programs
if @progs.nil?
@progs = []
self[:program_count].times do |i|
@progs << self[:programs][i]
end
end
@progs
end
def tsid?
self[:tsid_detected] == 1
end
def tsid
"0x%04X" % self[:tsid]
end
end
# HDHomeRun capture statistics for a given tuner
#
# packets:: Number of packets captured
# network_errors:: Number of network errors
# transport_errors:: Number of transport errors
# sequence_errors:: Number of sequence errors
# overflow_errors:: Number of overflow errors
#
class Stats < FFI::Struct
layout :packets, :uint,
:network_errors, :uint,
:transport_errors, :uint,
:sequence_errors, :uint,
:overflow_errors, :uint
%w{packets network_errors transport_errors
sequence_errors overflow_errors}.each do |name|
define_method name do
send(:[], name.to_sym)
end
end
end
class Device < FFI::Struct
layout :cs, :pointer,
:vs, :pointer,
:dbg, :pointer,
:scan, :pointer,
:multicast_ip, :uint32,
:multicast_port, :uint16,
:device_id, :uint,
:lockkey, :uint32,
:name, [:char, 32],
:model, [:char, 32]
members.each do |name|
define_method name.to_s do
send(:[], name.to_sym)
end
end
end
# Discover device structure
#
# Silicon dust changed this structure at some point between
# revision 20100121 and 20110323, but the version number in the
# library filename was not changed by package maintainers for
# ubuntu. As a result, there's no simple way to determine which
# structure we should use. To work around this, the gem will
# assume the library has the newer structure unless the
# FFI_HDHOMERUN_OLD_DEVICE_STRUCT environment variable has been
# set.
#
class DiscoverDevice < FFI::Struct
if ENV['FFI_HDHOMERUN_OLD_DEVICE_STRUCT']
layout :ip_addr, :uint32,
:device_type, :uint32,
:device_id, :uint32
else
# Newer layout has support for :tuner_count
layout :ip_addr, :uint32,
:device_type, :uint32,
:device_id, :uint32,
:tuner_count, :uint8
define_method :tuner_count do
send(:[], :tuner_count)
end
end
%w{device_type device_id}.each do |name|
define_method name do
send(:[], name.to_sym)
end
end
def ip_addr
IPAddr.new(self[:ip_addr], Socket::AF_INET)
end
end
end
end