VDR.cgi/cgi-bin/vdr/epg.rb

252 lines
6.3 KiB
Ruby

require 'options'
class ::VDR::EPG
attr_reader :vdr
def initialize( vdr) @vdr = vdr end
def each( &e) select.each &e end
def parse( file = nil, &e) self.class.parse @vdr, file, &e end
def find_first( h = nil) find h do |entry| return entry end end
def self.parse vdr, file = nil, &e
file ||= ::EPGDATA || '/var/vdr/epg.data'
e ||= ::Array.new.method :push
ret, c, event = nil, "", ::VDR::EPG::Entry.new( vdr)
::File.open file do |f|
f.each do |line|
l = line.chomp![2..-1]
case line[0]
when ?C: c = l
when ?E: event = ::VDR::EPG::Entry.new vdr, c, l
when ?T: event.title = l
when ?S: event.short_text = l
when ?D: event.description = l
when ?X: event.streams.push l
when ?V: event.vps = l
when ?e: ret = e.call event
when ?c
else { :unexpected_epg => line }.dakknight
end
end
end
ret
end
def select h = nil, &e
e ? ::VDR::EPG::Select.new( self, h) : ::VDR::EPG::Select.new( self, h, &e)
end
def find h = nil, &e
s = select h
e ? s.each( &e) : s.to_a
end
end
class ::VDR::EPG::Select
attr_reader :epg, :between, :channel, :title, :description, :block
def each( &e) eval gen_filter end
def first() each do |entry| return entry end end
def initialize epg, h = nil, &e
h ||= {}
@block, @epg, @between, @channel, @title, @description = \
e, epg, h[:between], h[:channel], h[:title], h[:description]
@start, @stop, @duration = h[:start], h[:stop], h[:duration]
end
def gen_filter t = nil, p = nil, u = nil
s = []
s.push '@start === event.start' if @start
s.push '@stop === event.stop' if @stop
s.push '@duration === event.duration' if @duration
if @channel
@channel = ::VDR::EPG::Channel.new @vdr, @channel.to_s
s.push '@channel === entry.channel'
end
s.push '@description === entry.description' if @description
s.push '@title === entry.title' if @title
s.push 'event.vergleichen @between' if @between
s.push '@block.call( entry)' if @block
#s.push t || 'e.call( entry)'
s = <<-EOF
#{p || '@epg.parse do |entry|'}
event = entry.event
#{s.collect( & "(%s) || next".method( :%)).join "\n\t\t\t\t"}
#{t || 'e.call( entry)'}
#{u || 'end'}
EOF
s
end
def collect &e
ret []
eval gen_filter( 'ret.push( e.call( entry))')
ret
end
def to_a
ret = []
e = gen_filter( 'ret.push( entry)')
begin
eval e
rescue Object
File.open( '/tmp/vdr.cgi.debug', 'w+') do|f|
f.puts '='*80
f.puts e
f.puts '-'*80
f.puts "#{$!.message} (#{$!.class})"
f.puts "\t" + $!.backtrace.join( "\n\t")
end
raise $!
end
ret
end
end
class ::VDR::EPG::Entry
attr_accessor :short_text, :description, :streams, :vps
attr_reader :title, :vdr, :event, :channel
def title=( value) @title = value.to_s end
def initialize vdr, c = ::VDR::EPG::Channel.new( vdr), e = "", t = "", s = "", d = "", x = [], v = ""
::Kernel.expect ::VDR, vdr
@vdr, self.channel, self.event, self.title, self.short_text,
self.description, self.streams, self.vps = vdr, c, e, t, s, d, x, v
end
def channel= value
value = ::VDR::EPG::Channel.new @vdr, value if value.kind_of? ::String
::Kernel.expect ::VDR::EPG::Channel, value
@channel = value
end
def event= value
value = ::VDR::EPG::Event.new value if value.kind_of? ::String
::Kernel.expect ::VDR::EPG::Event, value
@event = value
end
def to_timer
e = self.event
::VDR::Timer.new @vdr, 3, self.channel, ::VDR::Timer::Day.new( e.start),
::VDR::Timer::Clock.new( e.start.hour, e.start.min),
::VDR::Timer::Clock.new( e.stop.hour, e.stop.min),
99, 99, self.title, self.description
end
def record?
timer, chan = self.to_timer, self.channel
r = []
vdr.lstt do |a|
if timer.channel == a.channel && (x = (timer =~ a))
r.push x
end
end
r.uniq
end
def inspect
"#<#{self.class} #{self.channel.inspect} #{self.title.inspect} #{self.event.inspect}>"
end
def vergleichen m
[ :short_text, :description, :streams, :vps, :title, :vdr, :event,
:channel ].each do |k|
m[k] ? m[k] === e.method( k) : true
end
end
alias =~ vergleichen
end
class ::VDR::EPG::Event
attr_reader :id, :start, :duration, :table_id
def id=( value) @id = value.to_i end
def duration=( value) @duration = value.to_i end
def table_id=( value) @table_id = value end
def to_s() [ @id, @start.to_i, @duration, @table_id].compact.join " " end
def initialize id = 0, start = nil, duration = nil, table_id = nil
self.id, self.start, self.duration, self.table_id = if id.kind_of? ::String
id.split " "
else [ id, start, duration, table_id ]
end
end
def stop() self.start + self.duration end
def stop= value
value = ::Time.at value unless value.kind_of? ::Time
self.duration = (value - self.start).to_i
end
def start= value
value = ::Time.at value.to_i unless value.kind_of? ::Time
@start = value
end
def vergleichen value
start, stop = self.start.to_i, self.stop.to_i
case value
when ::Numeric, ::Time: (start .. stop) === value.to_i
when ::Range
value = value.begin.to_i..value.end.to_i
value.include?( start) || value.include?( stop) ||
(start..stop).include?( value.begin)
when self.class
vstart, vstop = value.start.to_i, value.stop.to_i
(start..stop) === vstart || (start..stop) === vstop ||
(vstart..vstop) === start
else raise ::ArgumentError, "#{value.inspect}"
end
end
alias =~ vergleichen
def inspect
"#<#{self.class} #{self.start.inspect} #{self.duration.inspect}>"
end
end
class VDR::EPG::Channel
attr_reader :vdr, :id
def to_i() channel.number end
def name() @name || channel.name end
def initialize vdr, id = nil, name = nil
@vdr = vdr
self.id, self.name = if id.nil? then [ '', '' ]
elsif name.nil? then id.to_s.split ' ', 2
else [ id, name ]
end
end
def id= value
::Kernel.expect ::String, value
@channel = nil
@id = value
end
def channel
return @channel if @channel
source, tid, rid, nid = @id.split "-"
@channel = @vdr.lstc.find do |c|
c.source == source && c.tid == tid && c.rid == rid && c.nid == nid
end
end
def name= value
::Kernel.expect [::String, nil], value
@name = value
end
def == v
case v
when ::Numeric: to_i == v
when ::VDR::EPG::Channel: self.id == v.id
else super v
end
end
def inspect
"#<#{self.class} #{self.name.inspect} #{self.to_i.inspect} @id=#{self.id.inspect}>"
end
end