3 from datetime
import datetime
4 from xml
.dom
import minidom
6 from lrucache
import LRUCache
11 TRIBUNE_CR
= ' Copyright Tribune Media Services, Inc.'
13 tivo_cache
= LRUCache(50)
15 def tag_data(element
, tag
):
16 for name
in tag
.split('/'):
17 new_element
= element
.getElementsByTagName(name
)
20 element
= new_element
[0]
21 if not element
.firstChild
:
23 return element
.firstChild
.data
25 def _vtag_data(element
, tag
):
26 for name
in tag
.split('/'):
27 new_element
= element
.getElementsByTagName(name
)
30 element
= new_element
[0]
31 elements
= element
.getElementsByTagName('element')
32 return [x
.firstChild
.data
for x
in elements
if x
.firstChild
]
34 def _tag_value(element
, tag
):
35 item
= element
.getElementsByTagName(tag
)
37 value
= item
[0].attributes
['value'].value
38 name
= item
[0].firstChild
.data
39 return name
[0] + value
[0]
41 def from_text(full_path
):
43 path
, name
= os
.path
.split(full_path
)
44 for metafile
in [os
.path
.join(path
, 'default.txt'), full_path
+ '.txt',
45 os
.path
.join(path
, '.meta', name
) + '.txt']:
46 if os
.path
.exists(metafile
):
47 for line
in file(metafile
):
48 if line
.strip().startswith('#') or not ':' in line
:
50 key
, value
= [x
.strip() for x
in line
.split(':', 1)]
51 if key
.startswith('v'):
53 metadata
[key
].append(value
)
55 metadata
[key
] = [value
]
61 base_path
, title
= os
.path
.split(full_path
)
62 mtime
= os
.stat(full_path
).st_mtime
65 originalAirDate
= datetime
.fromtimestamp(mtime
)
67 metadata
= {'title': '.'.join(title
.split('.')[:-1]),
68 'originalAirDate': originalAirDate
.isoformat()}
70 metadata
.update(from_text(full_path
))
74 def from_container(xmldoc
):
77 keys
= {'title': 'Title', 'episodeTitle': 'EpisodeTitle',
78 'description': 'Description', 'seriesId': 'SeriesId',
79 'episodeNumber': 'EpisodeNumber', 'tvRating': 'TvRating',
80 'displayMajorNumber': 'SourceChannel', 'callsign': 'SourceStation'}
82 details
= xmldoc
.getElementsByTagName('Details')[0]
85 data
= tag_data(details
, keys
[key
])
87 if key
== 'description':
88 data
= data
.replace(TRIBUNE_CR
, '')
89 elif key
== 'tvRating':
91 elif key
== 'displayMajorNumber':
93 data
, metadata
['displayMinorNumber'] = data
.split('-')
98 def from_details(xmldoc
):
101 showing
= xmldoc
.getElementsByTagName('showing')[0]
102 program
= showing
.getElementsByTagName('program')[0]
104 items
= {'description': 'program/description',
105 'title': 'program/title',
106 'episodeTitle': 'program/episodeTitle',
107 'episodeNumber': 'program/episodeNumber',
108 'seriesId': 'program/series/uniqueId',
109 'seriesTitle': 'program/series/seriesTitle',
110 'originalAirDate': 'program/originalAirDate',
111 'isEpisode': 'program/isEpisode',
112 'movieYear': 'program/movieYear',
113 'partCount': 'partCount',
114 'partIndex': 'partIndex'}
117 data
= tag_data(showing
, item
)
119 if item
== 'description':
120 data
= data
.replace(TRIBUNE_CR
, '')
121 metadata
[item
] = data
123 vItems
= ['vActor', 'vChoreographer', 'vDirector',
124 'vExecProducer', 'vProgramGenre', 'vGuestStar',
125 'vHost', 'vProducer', 'vWriter']
128 data
= _vtag_data(program
, item
)
130 metadata
[item
] = data
132 sb
= showing
.getElementsByTagName('showingBits')
134 metadata
['showingBits'] = sb
[0].attributes
['value'].value
136 for tag
in ['starRating', 'mpaaRating', 'colorCode']:
137 value
= _tag_value(program
, tag
)
139 metadata
[tag
] = value
141 rating
= _tag_value(showing
, 'tvRating')
143 metadata
['tvRating'] = 'x' + rating
[1]
147 def from_tivo(full_path
):
148 if full_path
in tivo_cache
:
149 return tivo_cache
[full_path
]
151 tdcat_path
= config
.get_bin('tdcat')
152 tivo_mak
= config
.get_server('tivo_mak')
153 if tdcat_path
and tivo_mak
:
154 tcmd
= [tdcat_path
, '-m', tivo_mak
, '-2', full_path
]
155 tdcat
= subprocess
.Popen(tcmd
, stdout
=subprocess
.PIPE
)
156 xmldoc
= minidom
.parse(tdcat
.stdout
)
157 metadata
= from_details(xmldoc
)
158 tivo_cache
[full_path
] = metadata