1 | #!/usr/local/bin/python |
---|
2 | # -*- coding: UTF-8 -*- |
---|
3 | #--------------------------- |
---|
4 | # Name: mythvidexport.py |
---|
5 | # Python Script |
---|
6 | # Author: Raymond Wagner |
---|
7 | # Purpose |
---|
8 | # This python script is intended to function as a user job, run through |
---|
9 | # mythjobqueue, capable of exporting recordings into MythVideo. |
---|
10 | #--------------------------- |
---|
11 | __title__ = "MythVidExport" |
---|
12 | __author__ = "Raymond Wagner" |
---|
13 | __version__= "v0.5.0" |
---|
14 | |
---|
15 | usage_txt = """ |
---|
16 | This script can be run from the command line, or called through the mythtv |
---|
17 | jobqueue. The input format will be: |
---|
18 | mythvidexport.py [options] <--chanid <channel id>> <--starttime <start time>> |
---|
19 | --- or --- |
---|
20 | mythvidexport.py [options] %JOBID% |
---|
21 | |
---|
22 | Options are: |
---|
23 | --mformat <format string> |
---|
24 | --tformat <format string> |
---|
25 | --gformat <format string> |
---|
26 | overrides the stored format string for a single run |
---|
27 | --listingonly |
---|
28 | use EPG data rather than grabbers for metadata |
---|
29 | will still try to grab episode and season information from ttvdb.py |
---|
30 | |
---|
31 | Additional functions are available beyond exporting video |
---|
32 | mythvidexport.py <options> |
---|
33 | -h, --help show this help message |
---|
34 | -p, --printformat print existing format strings |
---|
35 | -f, --helpformat lengthy description for formatting strings |
---|
36 | --mformat <string> replace existing Movie format |
---|
37 | --tformat <string> replace existing TV format |
---|
38 | --gformat <string> replace existing Generic format |
---|
39 | """ |
---|
40 | |
---|
41 | from MythTV import MythTV, MythDB, MythLog, MythVideo, Program, FileTransfer, Job |
---|
42 | #from MythTV.MythLog import EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG, ALL |
---|
43 | from socket import gethostname |
---|
44 | from urllib import urlretrieve |
---|
45 | from optparse import OptionParser |
---|
46 | import sys, re, os, time |
---|
47 | |
---|
48 | |
---|
49 | #log = MythLog(NOTICE, 'MythVidExport.py') |
---|
50 | |
---|
51 | class VIDEO: |
---|
52 | job = None |
---|
53 | dest = None |
---|
54 | |
---|
55 | viddata = {} |
---|
56 | cast = [] |
---|
57 | genre = [] |
---|
58 | country = [] |
---|
59 | imageurl = {'coverfile':None, 'banner':None, 'fanart':None, 'screenshot':None} |
---|
60 | image = {'coverfile':None, 'banner':None, 'fanart':None, 'screenshot':None} |
---|
61 | |
---|
62 | def __init__(self, opts, jobid): |
---|
63 | if jobid: |
---|
64 | self.job = Job(jobid) |
---|
65 | self.chanid = self.job.chanid |
---|
66 | self.rtime = int("%04d%02d%02d%02d%02d%02d" % self.job.starttime.timetuple()[0:6]) |
---|
67 | self.jobhost = self.job.host |
---|
68 | self.job.setStatus(3) |
---|
69 | else: |
---|
70 | self.chanid = opts.chanid |
---|
71 | self.rtime = opts.starttime |
---|
72 | self.jobhost = gethostname() |
---|
73 | |
---|
74 | self.opts = opts |
---|
75 | self.mythdb = MythDB() |
---|
76 | self.cursor = self.mythdb.cursor() |
---|
77 | |
---|
78 | # load grabber scripts |
---|
79 | self.get_grabber() |
---|
80 | |
---|
81 | # load formatting strings |
---|
82 | self.get_fmt() |
---|
83 | if opts.tformat: |
---|
84 | selt.tfmt = opts.tformat |
---|
85 | if opts.mformat: |
---|
86 | self.mfmt = opts.mformat |
---|
87 | if opts.gformat: |
---|
88 | self.gfmt = opts.gformat |
---|
89 | |
---|
90 | # process file |
---|
91 | self.get_source() |
---|
92 | self.get_meta() |
---|
93 | self.get_dest() |
---|
94 | |
---|
95 | # save file |
---|
96 | self.copy() |
---|
97 | self.write_meta() |
---|
98 | self.seekdata() |
---|
99 | |
---|
100 | def get_source(self): |
---|
101 | ## connects to myth data socket and finds recording |
---|
102 | mythinst = MythTV() |
---|
103 | self.prog = mythinst.getRecording(self.chanid,self.rtime) |
---|
104 | |
---|
105 | self.srchost = self.prog.hostname |
---|
106 | self.source = mythinst.getCheckfile(self.prog) |
---|
107 | |
---|
108 | def get_grabber(self): |
---|
109 | # grab ttvdb commands |
---|
110 | glist = ('TitleSub','Data','Poster','Fanart','Banner','Screenshot') |
---|
111 | self.ttvdb = {} |
---|
112 | for cmd in glist: |
---|
113 | self.ttvdb[cmd] = self.mythdb.getSetting('mythvideo.TV%sCommandLine' % cmd,self.jobhost) |
---|
114 | |
---|
115 | # insert optional ttvdb config file |
---|
116 | if os.access(os.path.expanduser("~/.mythtv/ttvdb.conf"),os.F_OK): |
---|
117 | ttvdbconf = os.path.expanduser("~/.mythtv/ttvdb.conf") |
---|
118 | for cmd in glist: |
---|
119 | tmp = self.ttvdb[cmd].split(' ') |
---|
120 | tmp.insert(1,'-c '+ttvdbconf) |
---|
121 | self.ttvdb[cmd] = ' '.join(tmp) |
---|
122 | |
---|
123 | # grab tmdb commands |
---|
124 | glist = ('List','Data','Poster','Fanart') |
---|
125 | self.tmdb = {} |
---|
126 | for cmd in glist: |
---|
127 | self.tmdb[cmd] = self.mythdb.getSetting('Movie%sCommandLine' % cmd,self.jobhost) |
---|
128 | |
---|
129 | def get_meta(self): |
---|
130 | if self.prog.subtitle: # subtitle exists, assume tv show |
---|
131 | self.get_ttvdb() |
---|
132 | else: # assume movie |
---|
133 | self.get_tmdb() |
---|
134 | |
---|
135 | def get_ttvdb(self): |
---|
136 | ## grab season and episode number from thetvdb.com, exit if failed |
---|
137 | fp = os.popen("""%s "%s" "%s" """ % (self.ttvdb['TitleSub'],self.prog.title,self.prog.subtitle),"r") |
---|
138 | match = re.search("S(?P<season>[0-9]*)E(?P<episode>[0-9]*)", fp.read()) |
---|
139 | fp.close() |
---|
140 | if match is None: |
---|
141 | # log.warning('Grabber error', "TTVDB.py failed to get season/episode numbers for %s - %s. Reverting to generic export." % (self.prog.title, self.prog.subtitle)) |
---|
142 | self.get_generic() |
---|
143 | return |
---|
144 | |
---|
145 | self.viddata['season'] = int(match.group('season')) |
---|
146 | self.viddata['episode'] = int(match.group('episode')) |
---|
147 | |
---|
148 | if self.opts.listingonly: # do not grab subsequent information from ttvdb |
---|
149 | self.get_generic() |
---|
150 | |
---|
151 | else: # gather remaining data |
---|
152 | self.process_meta("""%s "%s" %d %d""" % (self.ttvdb['Data'],self.prog.title,self.viddata['season'],self.viddata['episode'])) |
---|
153 | self.viddata['title'] = self.prog.title |
---|
154 | |
---|
155 | # grab links to images |
---|
156 | link = re.compile('http://.*thetvdb\.com/.*') |
---|
157 | for (key, grabber) in (('coverfile','Poster'),('banner','Banner'),('fanart','Fanart'),('screenshot','Screenshot')): |
---|
158 | fp = os.popen("""%s "%s" %d %d""" % (self.ttvdb[grabber],self.viddata['title'],self.viddata['season'],self.viddata['episode'])) |
---|
159 | res = fp.read() |
---|
160 | if self.opts.sim: |
---|
161 | print grabber |
---|
162 | print res |
---|
163 | match = link.search(res) |
---|
164 | fp.close() |
---|
165 | if match: |
---|
166 | self.imageurl[key] = match.group() |
---|
167 | if key == 'screenshot': |
---|
168 | self.image[key] = self.prog.title |
---|
169 | self.image[key] = match.group() |
---|
170 | |
---|
171 | # set some common data |
---|
172 | self.country = () |
---|
173 | self.viddata['showlevel'] = 1 |
---|
174 | self.viddata['rating'] = 'NR' |
---|
175 | self.viddata['coverfile'] = 'No Cover' |
---|
176 | self.type = 'TV' |
---|
177 | |
---|
178 | def get_tmdb(self): |
---|
179 | if self.opts.listingonly: # do not grab from tmdb |
---|
180 | self.get_generic() |
---|
181 | else: # find inetref from tmdb |
---|
182 | match = None |
---|
183 | fp = os.popen("""%s "%s" """ % (self.tmdb['List'], self.prog.title)) |
---|
184 | if self.prog.year: |
---|
185 | match = re.search("(?P<inetref>[0-9]*):%s[ ]*\(%s\)" % (self.prog.title, self.prog.year), fp.read()) |
---|
186 | else: |
---|
187 | match = re.search("(?P<inetref>[0-9]*):%s[ ]*\([0-9]*\)" % self.prog.title, fp.read()) |
---|
188 | fp.close() |
---|
189 | if match is None: |
---|
190 | # log.warning('Grabber error', "TMDB.py failed to find matching movie for %s. Reverting to generic export." % self.prog.title) |
---|
191 | self.get_generic() |
---|
192 | return |
---|
193 | |
---|
194 | # gather remanining data |
---|
195 | self.viddata['inetref'] = match.group('inetref') |
---|
196 | self.process_meta("%s %s" % (self.tmdb['Data'], match.group('inetref'))) |
---|
197 | |
---|
198 | # grab links to images |
---|
199 | link = re.compile('http://images.themoviedb.org/.*') |
---|
200 | for (key, grabber) in (('coverfile','Poster'),('fanart','Fanart')): |
---|
201 | fp = os.popen("%s %s" % (self.tmdb[grabber], self.viddata['inetref'])) |
---|
202 | match = link.search(fp.read()) |
---|
203 | fp.close() |
---|
204 | if match: |
---|
205 | self.image[key] = match.group() |
---|
206 | |
---|
207 | # set some common data |
---|
208 | self.country = () |
---|
209 | self.viddata['showlevel'] = 1 |
---|
210 | self.viddata['rating'] = 'NR' |
---|
211 | self.viddata['coverfile'] = 'No Cover' |
---|
212 | self.type = 'MOVIE' |
---|
213 | |
---|
214 | def get_generic(self): |
---|
215 | # pull available program data |
---|
216 | self.viddata['title'] = self.prog.title |
---|
217 | if self.prog.subtitle: |
---|
218 | self.viddata['subtitle'] = self.prog.subtitle |
---|
219 | if self.prog.description: |
---|
220 | self.viddata['plot'] = self.prog.description |
---|
221 | if self.prog.year: |
---|
222 | self.viddata['year'] = self.prog.year |
---|
223 | self.viddata['length'] = str(int((self.prog.recendts-self.prog.recstartts).seconds/60)) |
---|
224 | self.viddata['inetref'] = '00000000' |
---|
225 | self.viddata['director'] = self.mythdb.getCast(self.chanid, self.rtime, roles='director') |
---|
226 | if len(self.viddata['director']) == 0: |
---|
227 | self.viddata['director'] = 'NULL' |
---|
228 | else: |
---|
229 | self.viddata['director'] = self.viddata['director'][0] |
---|
230 | self.cast = self.mythdb.getCast(self.chanid, self.rtime, roles=('actor','guest_star','host','commentator','guest')) |
---|
231 | self.country = () |
---|
232 | self.viddata['showlevel'] = 1 |
---|
233 | self.viddata['rating'] = 'NR' |
---|
234 | self.viddata['coverfile'] = 'No Cover' |
---|
235 | self.type = 'GENERIC' |
---|
236 | |
---|
237 | |
---|
238 | def process_meta(self, command): |
---|
239 | # process grabber command and pull available data |
---|
240 | fp = os.popen(command) |
---|
241 | res = fp.read() |
---|
242 | fp.close() |
---|
243 | dict = {} |
---|
244 | for point in res.split('\n')[:-1]: |
---|
245 | if point.find(':') == -1: |
---|
246 | continue |
---|
247 | key,dat = point.split(':',1) |
---|
248 | dict[key] = dat |
---|
249 | for (dbkey, datkey) in (('title','Title'),('subtitle','Subtitle'),('director','Director'), |
---|
250 | ('plot','Plot'),('inetref','Seriesid'), ('year','Year'), |
---|
251 | ('userrating','UserRating'),('length','Runtime')): |
---|
252 | if datkey in dict.keys(): |
---|
253 | self.viddata[dbkey] = dict[datkey].strip() |
---|
254 | if 'Cast' in dict.keys(): |
---|
255 | self.cast = tuple(dict['Cast'].split(', ')) |
---|
256 | if 'Genres' in dict.keys(): |
---|
257 | self.genre = tuple(dict['Genres'].split(', ')) |
---|
258 | |
---|
259 | def get_dest(self): |
---|
260 | |
---|
261 | subpath = None |
---|
262 | if self.type == 'TV': |
---|
263 | subpath = self.process_fmt(self.tfmt) |
---|
264 | elif self.type == 'MOVIE': |
---|
265 | subpath = self.process_fmt(self.mfmt) |
---|
266 | elif self.type == 'GENERIC': |
---|
267 | subpath = self.process_fmt(self.gfmt) |
---|
268 | subpath += self.source[self.source.rfind('.'):] |
---|
269 | |
---|
270 | res = self.mythdb.getStorageGroup('Videos',self.jobhost) |
---|
271 | if len(res): |
---|
272 | self.dest = res[0]['dirname']+subpath |
---|
273 | self.destdb = subpath |
---|
274 | else: |
---|
275 | self.dest = self.mythdb.getSetting("VideoStartupDir",self.jobhost)+'/'+subpath |
---|
276 | self.destdb = self.dest |
---|
277 | |
---|
278 | tmppath = self.dest[0:self.dest.rfind('/')] |
---|
279 | if not os.access(tmppath,os.F_OK): |
---|
280 | os.makedirs(tmppath) |
---|
281 | |
---|
282 | def get_fmt(self): |
---|
283 | self.tfmt = self.mythdb.getSetting('mythvideo.TVexportfmt') |
---|
284 | if not self.tfmt: |
---|
285 | self.tfmt = 'Television/%TITLE%/Season %SEASON%/%TITLE% - S%SEASON%E%EPISODEPAD% - %SUBTITLE%' |
---|
286 | self.mfmt = self.mythdb.getSetting('mythvideo.MOVIEexportfmt') |
---|
287 | if not self.mfmt: |
---|
288 | self.mfmt = 'Movies/%TITLE%' |
---|
289 | self.gfmt = self.mythdb.getSetting('mythvideo.GENERICexportfmt') |
---|
290 | if not self.gfmt: |
---|
291 | self.gfmt = 'Videos/%TITLE%' |
---|
292 | |
---|
293 | def process_fmt(self, fmt): |
---|
294 | # replace fields from viddata |
---|
295 | rep = ( ('%TITLE%','title','%s'),('%SUBTITLE%','subtitle','%s'), |
---|
296 | ('%SEASON%','season','%d'),('%SEASONPAD%','season','%02d'), |
---|
297 | ('%EPISODE%','episode','%d'),('%EPISODEPAD%','episode','%02d'), |
---|
298 | ('%YEAR%','year','%s'),('%DIRECTOR%','director','%s')) |
---|
299 | for (tag, data, format) in rep: |
---|
300 | if data in self.viddata.keys(): |
---|
301 | fmt = fmt.replace(tag,format % self.viddata[data]) |
---|
302 | else: |
---|
303 | fmt = fmt.replace(tag,'') |
---|
304 | |
---|
305 | # replace fields from program data |
---|
306 | rep = ( ('%HOSTNAME','hostname','%s'),('%STORAGEGROUP%','storagegroup','%s')) |
---|
307 | for (tag, data, format) in rep: |
---|
308 | data = eval('self.prog.%s' % data) |
---|
309 | fmt = fmt.replace(tag,format % data) |
---|
310 | |
---|
311 | # fmt = fmt.replace('%CARDID%',self.prog.cardid) |
---|
312 | # fmt = fmt.replace('%CARDNAME%',self.prog.cardid) |
---|
313 | # fmt = fmt.replace('%SOURCEID%',self.prog.cardid) |
---|
314 | # fmt = fmt.replace('%SOURCENAME%',self.prog.cardid) |
---|
315 | # fmt = fmt.replace('%CHANNUM%',self.prog.channum) |
---|
316 | # fmt = fmt.replace('%CHANNAME%',self.prog.cardid) |
---|
317 | |
---|
318 | if len(self.genre): |
---|
319 | fmt = fmt.replace('%GENRE%',self.genre[0]) |
---|
320 | else: |
---|
321 | fmt = fmt.replace('%GENRE%','') |
---|
322 | # if len(self.country): |
---|
323 | # fmt = fmt.replace('%COUNTRY%',self.country[0]) |
---|
324 | # else: |
---|
325 | # fmt = fmt.replace('%COUNTRY%','') |
---|
326 | return fmt |
---|
327 | |
---|
328 | def copy(self): |
---|
329 | if self.opts.skip: |
---|
330 | return |
---|
331 | if self.opts.sim: |
---|
332 | print 'Transferring from "%s:%s" to "%s"' % (self.srchost,self.source,self.dest) |
---|
333 | return |
---|
334 | srcp = None |
---|
335 | dtime = None |
---|
336 | |
---|
337 | # log.notice('Starting transfer','from "%s:%s" to "%s"' % (self.srchost,self.source,self.dest)) |
---|
338 | stime = time.time() |
---|
339 | ctime = time.time() |
---|
340 | if os.access(self.source,os.F_OK): |
---|
341 | srcp = open(self.source,'r') |
---|
342 | else: |
---|
343 | srcp = FileTransfer(self.prop) |
---|
344 | destp = open(self.dest,'w') |
---|
345 | srcsize = self.prog.filesize |
---|
346 | destsize = [0,0,0,0,0,0,0,0,0,0] |
---|
347 | if self.job: |
---|
348 | self.job.setStatus(4) |
---|
349 | tsize = 2**18 |
---|
350 | while tsize == 2**18: |
---|
351 | if (srcsize - destp.tell()) < tsize: |
---|
352 | tsize = srcsize - destp.tell() |
---|
353 | if time.time() - ctime > 4: |
---|
354 | ctime = time.time() |
---|
355 | destsize.append(destp.tell()) |
---|
356 | rem = srcsize - destp.tell() |
---|
357 | if destsize[0]: |
---|
358 | dtime = 40 |
---|
359 | else: |
---|
360 | dtime = int(ctime - stime) |
---|
361 | rate = (destp.tell() - destsize.pop(0))/dtime |
---|
362 | remt = rem/rate |
---|
363 | if self.job: |
---|
364 | self.job.setComment("%02d%% complete - %s seconds remaining" % (destsize[9]*100/srcsize, remt)) |
---|
365 | destp.write(srcp.read(tsize)) |
---|
366 | |
---|
367 | srcp.close() |
---|
368 | destp.close() |
---|
369 | # log.notice('Transfer complete','%d seconds elapsed' % int(time.time()-stime)) |
---|
370 | if self.job: |
---|
371 | self.job.setComment("Complete - %d seconds elapsed" % (int(time.time()-stime))) |
---|
372 | self.job.setStatus(256) |
---|
373 | |
---|
374 | |
---|
375 | def write_meta(self): |
---|
376 | mythvid = MythVideo() |
---|
377 | mythtv = MythTV() |
---|
378 | self.viddata['filename'] = self.destdb |
---|
379 | self.viddata['host'] = self.jobhost |
---|
380 | |
---|
381 | |
---|
382 | intid = mythvid.getMetadataId(self.destdb) |
---|
383 | if intid: |
---|
384 | if self.opts.sim: |
---|
385 | print "Existing entry found at [%d], updating with:" % intid |
---|
386 | print self.viddata |
---|
387 | else: |
---|
388 | mythvid.setMetadata(self.viddata,intid) |
---|
389 | else: |
---|
390 | if self.opts.sim: |
---|
391 | print "Creating new entry using:" |
---|
392 | print self.viddata |
---|
393 | else: |
---|
394 | intid = mythvid.setMetadata(self.viddata) |
---|
395 | for name in self.cast: |
---|
396 | if self.opts.sim: |
---|
397 | print "Adding cast member: " +name |
---|
398 | else: |
---|
399 | mythvid.setCast(name, intid) |
---|
400 | self.write_image('coverfile',intid) |
---|
401 | self.write_image('banner',intid) |
---|
402 | self.write_image('fanart',intid) |
---|
403 | if self.job: |
---|
404 | self.job.setStatus(272) |
---|
405 | |
---|
406 | def write_image(self,mode,intid): |
---|
407 | if not self.image[mode]: |
---|
408 | if self.opts.sim: |
---|
409 | print "No %s found" % mode |
---|
410 | return |
---|
411 | path = None |
---|
412 | dbpath = None |
---|
413 | SG = {'coverfile':'Coverart','banner':'Banners','fanart':'Fanart'} |
---|
414 | DB = {'coverfile':'VideoArtworkDir','banner':'mythvideo.bannerDir','fanart':'mythvideo.fanartDir'} |
---|
415 | mythvid = MythVideo() |
---|
416 | |
---|
417 | file = self.viddata['inetref']+'_'+self.image[mode][self.image[mode].rfind('/')+1:] |
---|
418 | |
---|
419 | res = self.mythdb.getStorageGroup(SG[mode],self.jobhost) |
---|
420 | if len(res): |
---|
421 | path = res[0]['dirname']+file |
---|
422 | dbpath = file |
---|
423 | else: |
---|
424 | path = self.mythdb.getSetting(DB[mode],self.jobhost)+'/'+file |
---|
425 | dbpath = path |
---|
426 | |
---|
427 | if self.opts.sim: |
---|
428 | print "Found %s at %s" % (mode,self.image[mode]) |
---|
429 | return |
---|
430 | |
---|
431 | if not os.access(path,os.F_OK): |
---|
432 | urlretrieve(self.image[mode],path) |
---|
433 | if (mode == 'coverfile') & (self.type == 'TV'): |
---|
434 | vdir = self.dest[:self.dest.rfind('/')] |
---|
435 | if not os.access(vdir+'folder.jpg',os.F_OK): |
---|
436 | urlretrieve(self.image[mode],vdir+'/folder.jpg') |
---|
437 | |
---|
438 | mythvid.setMetadata({mode:dbpath}, intid) |
---|
439 | |
---|
440 | def seekdata(self): |
---|
441 | if self.opts.sim: |
---|
442 | print "Running \"mythcommflag --rebuild --video '%s'\"" % self.dest |
---|
443 | return |
---|
444 | fp = os.popen("mythcommflag --rebuild --video '%s'" % self.dest) |
---|
445 | fp.close() |
---|
446 | |
---|
447 | def usage(): |
---|
448 | print("mythvidexport.py [options] [--chanid=<chanid> --starttime=<starttime> | <jobid>]") |
---|
449 | print(" This script can be run by specifing the channel and start time directly") |
---|
450 | print(" or by specifing the ID of a job in jobqueue") |
---|
451 | print("") |
---|
452 | print(" Run from the command line through the former:") |
---|
453 | print(" mythvidexport.py --chanid=1002 --starttime=200907010000") |
---|
454 | print(" Or from a user script through the latter:") |
---|
455 | print(" mythvidexport.py %JOBID%") |
---|
456 | print("") |
---|
457 | print(" Options:") |
---|
458 | print(" -h/--help and -f/--helpformat:") |
---|
459 | print(" return this help, or a listing of available formatting strings") |
---|
460 | print(" --fformat='<string>' and --dformat='<string>':") |
---|
461 | print(" override the stored formatting string in the database") |
---|
462 | print(" if no recording is specified, store format string to the database") |
---|
463 | |
---|
464 | def usage_format(): |
---|
465 | print("The default strings are:") |
---|
466 | print(" Television: 'Television/%TITLE%/Season %SEASON%/%TITLE% - S%SEASON%E%EPISODEPAD% - %SUBTITLE%'") |
---|
467 | print(" Movie: 'Movies/%TITLE%'") |
---|
468 | print(" Generic: 'Videos/%TITLE%'") |
---|
469 | print("") |
---|
470 | print("Available strings:") |
---|
471 | print(" %TITLE%: series title") |
---|
472 | print(" %SUBTITLE%: episode title") |
---|
473 | print(" %SEASON%: season number") |
---|
474 | print(" %SEASONPAD%: season number, padded to 2 digits") |
---|
475 | print(" %EPISODE%: episode number") |
---|
476 | print(" %EPISODEPAD%: episode number, padded to 2 digits") |
---|
477 | print(" %YEAR%: year") |
---|
478 | print(" %DIRECTOR%: director") |
---|
479 | # print(" %CARDID%: ID of tuner card used to record show") |
---|
480 | # print(" %CARDNAME%: name of tuner card used to record show") |
---|
481 | # print(" %SOURCEID%: ID of video source used to record show") |
---|
482 | # print(" %SOURCENAME%: name of video source used to record show") |
---|
483 | print(" %HOSTNAME%: backend used to record show") |
---|
484 | print(" %STORAGEGROUP%: storage group containing recorded show") |
---|
485 | # print(" %CHANNUM%: ID of channel used to record show") |
---|
486 | # print(" %CHANNAME%: name of channel used to record show") |
---|
487 | print(" %GENRE%: first genre listed for recording") |
---|
488 | # print(" %COUNTRY%: first country listed for recording") |
---|
489 | |
---|
490 | def print_format(): |
---|
491 | db = MythDB() |
---|
492 | tfmt = db.getSetting('mythvideo.TVexportfmt') |
---|
493 | if not tfmt: |
---|
494 | tfmt = 'Television/%TITLE%/%TITLE% - S%SEASON%E%EPISODEPAD% - %SUBTITLE%' |
---|
495 | mfmt = db.getSetting('mythvideo.MOVIEexportfmt') |
---|
496 | if not mfmt: |
---|
497 | mfmt = 'Movies/%TITLE%' |
---|
498 | gfmt = db.getSetting('mythvideo.GENERICexportfmt') |
---|
499 | if not gfmt: |
---|
500 | gfmt = 'Videos/%TITLE%' |
---|
501 | print "Current output formats:" |
---|
502 | print " TV: "+tfmt |
---|
503 | print " Movies: "+mfmt |
---|
504 | print " Generic: "+gfmt |
---|
505 | |
---|
506 | def main(): |
---|
507 | parser = OptionParser(usage="usage: %prog [options] [jobid]") |
---|
508 | |
---|
509 | parser.add_option("-f", "--helpformat", action="store_true", default=False, dest="fmthelp", |
---|
510 | help="Print explination of file format string.") |
---|
511 | parser.add_option("-p", "--printformat", action="store_true", default=False, dest="fmtprint", |
---|
512 | help="Print current file format string.") |
---|
513 | parser.add_option("--tformat", action="store", type="string", dest="tformat", |
---|
514 | help="Use TV format for current task. If no task, store in database.") |
---|
515 | parser.add_option("--mformat", action="store", type="string", dest="mformat", |
---|
516 | help="Use Movie format for current task. If no task, store in database.") |
---|
517 | parser.add_option("--gformat", action="store", type="string", dest="gformat", |
---|
518 | help="Use Generic format for current task. If no task, store in database.") |
---|
519 | parser.add_option("--chanid", action="store", type="int", dest="chanid", |
---|
520 | help="Use chanid for manual operation") |
---|
521 | parser.add_option("--starttime", action="store", type="int", dest="starttime", |
---|
522 | help="Use starttime for manual operation") |
---|
523 | parser.add_option("--listingonly", action="store_true", default=False, dest="listingonly", |
---|
524 | help="Use data from listing provider, rather than grabber") |
---|
525 | parser.add_option("-s", "--simulation", action="store_true", default=False, dest="sim", |
---|
526 | help="Simulation (dry run), no files are copied or new entries made") |
---|
527 | parser.add_option("--skip", action="store_true", default=False, dest="skip") # debugging use only |
---|
528 | |
---|
529 | opts, args = parser.parse_args() |
---|
530 | |
---|
531 | if opts.fmthelp: |
---|
532 | usage_format() |
---|
533 | sys.exit(0) |
---|
534 | |
---|
535 | if opts.fmtprint: |
---|
536 | usage_current() |
---|
537 | sys.exit(0) |
---|
538 | |
---|
539 | if opts.chanid and opts.starttime: |
---|
540 | export = VIDEO(opts,0) |
---|
541 | elif len(args) == 1: |
---|
542 | export = VIDEO(opts,int(args[0])) |
---|
543 | else: |
---|
544 | if opts.tformat or opts.mformat or opts.gformat: |
---|
545 | db = MythDB() |
---|
546 | if opts.tformat: |
---|
547 | print "Changing TV format to: "+opts.tformat |
---|
548 | db.setSetting('mythvideo.TVexportfmt',opts.tformat) |
---|
549 | if opts.mformat: |
---|
550 | print "Changing Movie format to: "+opts.mformat |
---|
551 | db.setSetting('mythvideo.MOVIEexportfmt',opts.mformat) |
---|
552 | if opts.gformat: |
---|
553 | print "Changing Generic format to: "+opts.gformat |
---|
554 | db.setSetting('mythvideo.GENERICexportfmt',opts.gformat) |
---|
555 | sys.exit(0) |
---|
556 | else: |
---|
557 | parser.print_help() |
---|
558 | sys.exit(2) |
---|
559 | |
---|
560 | if __name__ == "__main__": |
---|
561 | main() |
---|