Dies Aliquanti

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

iEPGクラス再び、RubyでPVRを作ろう!その15の2

ということで、ソースコード
 

#
# iEPGD Class
# (c) 2008-09 B.O
# re-written
# to support V1 and V2 of iEPG
# for V1 reference , http://350ml.net/labo/iepg.html
# thanks to "AKINO Yoh, 350ml.net"
#
require 'set'
class IEPG < Hash
# keywords
@@Header = "Content-type:"
@@V1SingleContent = "x-tv-program-info"
@@V2SingleContent = "x-tv-program-digital-info"
@@V1MultiContent = "x-multi-tv-program-info"
@@V2MultiContent = "x-multi-tv-program-digital-info"
@@V1Mandatory = [ "version:", "station:", "start:", "end:" ]
@@V1Axuary = [ "year:", "month:" , "date:", "program-title:",
"program-subtitle:", "performer:", "genre:" , "subgenre:" ]
@@V2Mandatory = [ "version:", "station:", "station-name:",
"program-title:", "program-id:", "start:", "end:" ]
@@V2Axuary = [ "year:", "month:" , "date:", "genre-1:", "subgenre-1:",
"program-subtitle:", "performer:", "genre:" , "subgenre:" ]

@@Memo = "_memo:" # adding memo section, needs to be
@@OneDay = 24*60*60
@@KeywordTimeRelated = Set[ "year:", "month:", "date:", "start:", "end:"]
attr_reader :timeStart, :timeEnd

# member method
def initialize
#self.default = ""
@timeStart = Time.now
@timeEnd = Time.now
end #def initialize

def to_s( format = nil )
if format != nil #summary mode
str = String.new( format )
for key, value in self
str.gsub!( /%#{key}/, value )
end
str.gsub!( /%D/ ,@timeStart.strftime("%Y%m%d"))
str.gsub!( /%eD/, @timeEnd.strftime("%Y%m%d"))
str.gsub!( /%T/, @timeStart.strftime("%H%M"))
str.gsub!( /%eT/, @timeEnd.strftime("%H%M"))
str.gsub!( /%%/, "%")
return str
end

#to reproduce .tvipd file single content mode
keywords = [ @@Header ] + ( ( self[ "version:" ] == "1" ) ?
( @@V1Mandatory + @@V1Axuary ) :
( @@V2Mandatory + @@V2Axuary ) )
keywordsInSelf = self.keys
s = ""
keywords.each {|key|
s += key + (self[ key ] || "") +"\n"
keywordsInSelf.delete( key )
}
# if there are anything else in hash, put them for safty sake, except _memo:
keywordsInSelf.each {|key|
if( key != @@Memo )
s += key + self[ key ] +"\n"
keywordsInSelf.delete( key )
end
}
# handle memo section
s += "\n" + (self[ @@Memo ] || "") +"\n"
end # to_s

def <=>( other )
self.timeStart <=> other.timeStart
end #def <=>( other )

def sameProgram?( other )
if (var = self[ "version:"]) != other[ "version:"]
raise __FILE__ + __LINE__.to_s + "Error mixed versions"
end
if ver == "2"
format = "%station:%program-id:"
else
format = "%station:%program-title:%D%T"
end
return self.to_s( format ) == other.to_s( format )
end #def sameProgram?( other )

def []=(key, value)
tmp = super
if( @@KeywordTimeRelated.include?( key ) )
timeNow = Time.now
year = self[ "year:" ] || timeNow.year
month = self[ "month:" ] || timeNow.month
day = self[ "date:" ] || timeNow.day
start_time = self[ "start:" ] || "0:0"
end_time = self[ "end:" ] || "0:0"

_start = start_time.split(":")
_end = end_time.split(":")
@timeStart = Time.local( year, month, day, _start[0], _start[1] )
@timeEnd = Time.local( year, month, day, _end[0], _end[1] )
if @timeEnd <= @timeStart
@timeEnd += @@OneDay
end
end
tmp
end
#
# class methods
#
def IEPG.File2Array( filespec )
f = open( filespec )
s = f.read
f.close
lines = s.split(/$/)
lines.each {|line| line.strip! }
IEPG.Lines2Array( lines )
end #def IEPG.File2Array( filespec )

def IEPG.Lines2Array( lines )
if lines[0] =~ /^Content-type: *application\/#{@@V1SingleContent}|#{@@V2SingleContent}/ # single content
if ( (tmp = IEPG::fromLines( lines )) != nil )
return [ tmp ]
end
elsif lines[0] =~ /^Content-type: *application\/#{@@V1MultiContent}|#{@@V2MultiContent}/ # multi contents
ar = Array.new
i, boundary = catch :found_boundary do
for i in 1..( lines.length() -1 ) # find boundary string
throw(:found_boundary,[i, $1.strip]) if lines[i] =~ /^boundary:(.*)$/
end
raise __FILE__ + __LINE__.to_s + "Error boundary cannot be found"
end # catch

for i in (i+1)..( lines.length() -1 )
break if lines[i] =~ /^#{boundary}/
end
s=i
for i in (i+1)..( lines.length() -1 )
if lines[i] =~ /^#{boundary}/
if (tmp = IEPG::fromLines( lines[(s+1)..(i-1)] ))
ar << tmp
end
s=i
return ar if lines[i] =~ /^#{boundary}--/ # really end
end
end #for
raise __FILE__ + __LINE__.to_s + "Error, maybe no BOUNDARY's end"
end #elsif lines[0] =~ /^Content-type: *appl...
raise __FILE__ + __LINE__.to_s + "Error, unexpected file format"
end # def IEPG.Lines2Array( inlines )

# read one iEPGd from lines
# return a iEPGd
def IEPG.fromLines( lines)
if !( lines[0] =~ /^#{@@Header} *(.*)$/ ) # checking 1st line
raise __FILE__ + __LINE__.to_s + "Error unexpected format :" + lines[0]
end
contentType = $1.strip
if !(contentType =~ /application\/#{@@V1SingleContent}|#{@@V2SingleContent}/ )
raise __FILE__ + __LINE__.to_s + "Error unexpected content type:" + lines[0]
end
#check charset
contentType =~ /charset=(.*)/
if (charset = $1.strip) != "shift_jis"
raise __FILE__ + __LINE__.to_s + "Error unexpected charset type:" + charset
end
tmp = IEPG.new
for i in 0..( lines.length() -1 )
break if !(lines[i] =~ /(.*?:)(.*)/ )
tmp[ "#{$1.strip}" ] = $2.strip
end #for
# check memo section
if lines[i].strip == ""
if (i = i +1 ) <= lines.length() -1
tmp[ @@Memo ] = lines[i..-1].join("\n")
end
end
# set year, month and date, if missing
now=Time.now
for key, value in { "year:" => "%Y", "month:" => "%m", "date:" => "%d" }
tmp[key] = tmp[key] || now.strftime( value )
end
tmp
end #def fromLines( lines)

end #class IEPG < Hash


#--------------------------------------------------------------

 



コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://diesaliquanti.blog.fc2.com/tb.php/668-dcebc205
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

まとめ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。