Support #1320 » vdrnfofs-0.8.1.diff
vdrnfofs-0.8.ralf/build/lib/vdrnfofs/config.py 2013-03-30 22:55:36.000000000 +0100 | ||
---|---|---|
show_subtitles = False
|
||
guess_episodes = False
|
vdrnfofs-0.8.ralf/build/lib/vdrnfofs/filesystemnodes.py 2013-03-31 14:53:51.000000000 +0200 | ||
---|---|---|
import glob
|
||
import os
|
||
import fuse
|
||
import logging
|
||
import re
|
||
import stat
|
||
import string
|
||
import datetime
|
||
import time
|
||
import config
|
||
from concatenated_file_reader import *
|
||
from vdr import *
|
||
vdrNameTranslation = string.maketrans('_', ' ')
|
||
vdrNameIgnore = '.,;:!?-+#&()°^<>[]\'"$'
|
||
episodeMarker = re.compile('^(S(?P<seasonA>\d\d?)E(?P<episodeA>\d\d?)|(?P<seasonB>\d\d?)(x|X)(?P<episodeB>\d\d?)) ')
|
||
class FileNode(object):
|
||
def __init__(self, path, extension):
|
||
self.path = path
|
||
... | ... | |
attr.st_mode = stat.S_IFREG | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH
|
||
attr.st_nlink = 1
|
||
attr.st_size = self.size()
|
||
timevalues = self.path.rsplit('/', 1)[1][:16].replace('.', '-').split('-')
|
||
timevalues = self.path.rsplit('/', 1)[1][:16].replace('.', '-').replace(':', '-').split('-')
|
||
attr.st_mtime = time.mktime(datetime.datetime(*[ int(s) for s in timevalues ]).timetuple())
|
||
attr.st_uid = orig.st_uid
|
||
attr.st_gid = orig.st_gid
|
||
... | ... | |
class NfoNode(FileNode):
|
||
def __init__(self, path):
|
||
def __init__(self, path, video_root = ''):
|
||
super(NfoNode, self).__init__(path, 'nfo')
|
||
self._nfo_content = None
|
||
virtual_path = path[len(video_root):].split('/')
|
||
global vdrNameTranslation
|
||
if len(virtual_path) > 1:
|
||
if len(virtual_path) > 2:
|
||
self.parent = virtual_path[-3].translate(vdrNameTranslation)
|
||
else:
|
||
self.parent = ''
|
||
name = virtual_path[-2]
|
||
if len(name) > 0:
|
||
if name[0] == '%':
|
||
name = name[1:]
|
||
self.name = name.translate(vdrNameTranslation)
|
||
else:
|
||
self.name = ''
|
||
self.is_episode = False
|
||
self.episode = ''
|
||
self.season = ''
|
||
def nfo_content(self):
|
||
global vdrNameIgnore
|
||
if not self._nfo_content:
|
||
info_path = self.path + '/info'
|
||
if not os.path.exists(info_path):
|
||
... | ... | |
if not os.path.exists(info_path):
|
||
info_path = None
|
||
info_vdr = InfoVdr(info_path)
|
||
self._nfo_content = """<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||
title = info_vdr['T']
|
||
show_subtitles = config.show_subtitles
|
||
if config.guess_episodes:
|
||
episodes_path = '/'.join(self.path.split('/')[:-2]) + '/.episodes'
|
||
if os.path.exists(episodes_path):
|
||
self.is_episode = True
|
||
elif len(self.parent) > 0:
|
||
titleTr = string.lower(title.translate(None, vdrNameIgnore))
|
||
parentTr = string.lower(self.parent.translate(None, vdrNameIgnore))
|
||
if (titleTr.startswith(parentTr) or titleTr.endswith(parentTr) or
|
||
parentTr.startswith(titleTr) or parentTr.endswith(titleTr)):
|
||
self.is_episode = True
|
||
if self.is_episode:
|
||
title = self.parent
|
||
show_subtitles = True
|
||
global episodeMarker
|
||
match = episodeMarker.match(self.name)
|
||
if match:
|
||
self.season = match.group('seasonA')
|
||
self.episode = match.group('episodeA')
|
||
if not self.season:
|
||
self.season = match.group('seasonB')
|
||
self.episode = match.group('episodeB')
|
||
self.season = string.lstrip(self.season, '0')
|
||
self.episode = string.lstrip(self.episode, '0')
|
||
if show_subtitles:
|
||
sub_title = info_vdr['S']
|
||
if len(sub_title.strip()) > 0:
|
||
title += " - "
|
||
if self.season:
|
||
title += str(self.season).zfill(2) + 'x' + str(self.episode).zfill(2) + ' '
|
||
title += sub_title
|
||
elif self.name != '':
|
||
title += " - " + self.name
|
||
if self.is_episode == True:
|
||
self._nfo_content = """<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||
<episodedetails>
|
||
<title>%s</title>
|
||
<plot>%s</plot>
|
||
<season>%s</season>
|
||
<episode>%s</episode>
|
||
</episodedetails>
|
||
""" % (title, info_vdr['D'], self.season, self.episode)
|
||
else:
|
||
self._nfo_content = """<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||
<movie>
|
||
<title>%s</title>
|
||
<plot>%s</plot>
|
||
</movie>
|
||
""" % (info_vdr['T'], info_vdr['D'])
|
||
""" % (title, info_vdr['D'])
|
||
return self._nfo_content
|
||
def size(self):
|
vdrnfofs-0.8.ralf/build/lib/vdrnfofs/vdrnfofs.py 2013-03-30 22:56:08.000000000 +0100 | ||
---|---|---|
import traceback
|
||
import logging
|
||
import config
|
||
from concatenated_file_reader import *
|
||
from vdr import *
|
||
from filesystemnodes import *
|
||
... | ... | |
elif virtual_file_extension == '.mpg':
|
||
return MpgNode(video_path)
|
||
elif virtual_file_extension == '.nfo':
|
||
return NfoNode(video_path)
|
||
return NfoNode(video_path, video)
|
||
else:
|
||
dir = video + path
|
||
if os.path.isdir(dir):
|
||
... | ... | |
self.video = ''
|
||
self.log = ''
|
||
self.loglevel = 'info'
|
||
self.guess_episode = False
|
||
self.show_subtitles = False
|
||
self.cache = NodeCache()
|
||
def getattr(self, path):
|
||
... | ... | |
logging.basicConfig(filename=self.log, level=getattr(logging, self.loglevel.upper()))
|
||
else:
|
||
logging.basicConfig(level=self.loglevel.upper())
|
||
if self.guess_episodes == None:
|
||
config.guess_episodes = True
|
||
if self.show_subtitles == None:
|
||
config.show_subtitles = True
|
||
logging.info('Starting vdrnfofs')
|
||
VdrNfoFsFile.video_root = self.video
|
||
... | ... | |
fs.parser.add_option(mountopt="video", default='', help="The video directory containing the VDR recordings")
|
||
fs.parser.add_option(mountopt="log", default='', help="The log file (default = console)")
|
||
fs.parser.add_option(mountopt="loglevel", default='info', help="The log level (debug, info, warning or error)")
|
||
fs.parser.add_option(mountopt="guess_episodes", default=False, help="try to guess episodes (title equals parent dir, filename starts with '0x0 ')")
|
||
fs.parser.add_option(mountopt="show_subtitles", default=False, help="add subtitles to title tags in nfo files")
|
||
fs.parse(values=fs, errex=1)
|
||
fs.main()
|
||
vdrnfofs-0.8.ralf/README 2013-03-31 15:33:55.347059523 +0200 | ||
---|---|---|
Title and plot are mapped from VDR's info file ('T' and 'D').
|
||
If it is an epsiode of a TV show the structure is like that:
|
||
<episodedetails>
|
||
<title>...</title>
|
||
<plot>...</plot>
|
||
<season>...</season>
|
||
<episode>...</episode>
|
||
</episodedetails>
|
||
How to install?
|
||
---------------
|
||
... | ... | |
and pass the option "allow_other" e.g.:
|
||
vdrnfofs /mnt/vdrnfofs -o video=/var/lib/video - o allow_other
|
||
If you want vdrnfofs to not only the the main movie title but add the movie
|
||
subtitle to the title tag you should add the "show_subtitles" option:
|
||
vdrnfofs /mnt/vdrnfofs fuse video=/var/lib/video,show_subtitles 0 0
|
||
Per default vdrnfofs does not deal with episodes at all. You can enable
|
||
epsiode detection heuristic by adding the "guess_episodes" option:
|
||
vdrnfofs /mnt/vdrnfofs fuse video=/var/lib/video,guess_episodes 0 0
|
||
vdrnfofs will then try to detect which vdr recording actually is a episode.
|
||
It does that by checking if the title of the recording ('T' in VDR's info file)
|
||
is the same as the directory the recording is stored in (or the title starts
|
||
with the directory name or ends with or vice versa). You can force a directory
|
||
to be a epsiode directory by simply do:
|
||
touch .episodes
|
||
in it. If a recording is handled as an episode vdrnfofs will add the movie
|
||
subtitle to its title. If no 'S' line is in the VDR info file it will reformat the
|
||
recording name as a subtitle. At the end vdrnfofs will try to guess season
|
||
and epsiode number from the recording name - if it starts with S01E05 or
|
||
01x05 it will take the first number for season and the second one for
|
||
episode tag in the generated .nfo file.
|
vdrnfofs-0.8.ralf/tests/test_nfo.py 2013-03-30 22:59:08.046239663 +0100 | ||
---|---|---|
self.assertEqual('sample-vdr1.7_2008-03-28.20.13.10-1.rec.nfo', node.file_system_name())
|
||
self.assertEqual('Movie Title', nfo.find('title').text)
|
||
self.assertEqual('A movie about something', nfo.find('plot').text)
|
||
def test_nfo_new_sub(self):
|
||
config.show_subtitles = True
|
||
node = get_node(self.video, '/sample-vdr1.7_2008-03-28.20.13.10-1.rec.nfo')
|
||
nfo = xml.etree.ElementTree.fromstring(node.read(0, 4096))
|
||
self.assertEqual('sample-vdr1.7_2008-03-28.20.13.10-1.rec.nfo', node.file_system_name())
|
||
self.assertEqual('Movie Title - Movie Subtitle', nfo.find('title').text)
|
||
self.assertEqual('A movie about something', nfo.find('plot').text)
|
vdrnfofs-0.8.ralf/vdrnfofs/config.py 2013-03-30 22:55:36.463122785 +0100 | ||
---|---|---|
show_subtitles = False
|
||
guess_episodes = False
|
vdrnfofs-0.8.ralf/vdrnfofs/filesystemnodes.py 2013-03-31 14:53:51.543829134 +0200 | ||
---|---|---|
import glob
|
||
import os
|
||
import fuse
|
||
import logging
|
||
import re
|
||
import stat
|
||
import string
|
||
import datetime
|
||
import time
|
||
import config
|
||
from concatenated_file_reader import *
|
||
from vdr import *
|
||
vdrNameTranslation = string.maketrans('_', ' ')
|
||
vdrNameIgnore = '.,;:!?-+#&()°^<>[]\'"$'
|
||
episodeMarker = re.compile('^(S(?P<seasonA>\d\d?)E(?P<episodeA>\d\d?)|(?P<seasonB>\d\d?)(x|X)(?P<episodeB>\d\d?)) ')
|
||
class FileNode(object):
|
||
def __init__(self, path, extension):
|
||
self.path = path
|
||
... | ... | |
attr.st_mode = stat.S_IFREG | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH
|
||
attr.st_nlink = 1
|
||
attr.st_size = self.size()
|
||
timevalues = self.path.rsplit('/', 1)[1][:16].replace('.', '-').split('-')
|
||
timevalues = self.path.rsplit('/', 1)[1][:16].replace('.', '-').replace(':', '-').split('-')
|
||
attr.st_mtime = time.mktime(datetime.datetime(*[ int(s) for s in timevalues ]).timetuple())
|
||
attr.st_uid = orig.st_uid
|
||
attr.st_gid = orig.st_gid
|
||
... | ... | |
class NfoNode(FileNode):
|
||
def __init__(self, path):
|
||
def __init__(self, path, video_root = ''):
|
||
super(NfoNode, self).__init__(path, 'nfo')
|
||
self._nfo_content = None
|
||
virtual_path = path[len(video_root):].split('/')
|
||
global vdrNameTranslation
|
||
if len(virtual_path) > 1:
|
||
if len(virtual_path) > 2:
|
||
self.parent = virtual_path[-3].translate(vdrNameTranslation)
|
||
else:
|
||
self.parent = ''
|
||
name = virtual_path[-2]
|
||
if len(name) > 0:
|
||
if name[0] == '%':
|
||
name = name[1:]
|
||
self.name = name.translate(vdrNameTranslation)
|
||
else:
|
||
self.name = ''
|
||
self.is_episode = False
|
||
self.episode = ''
|
||
self.season = ''
|
||
def nfo_content(self):
|
||
global vdrNameIgnore
|
||
if not self._nfo_content:
|
||
info_path = self.path + '/info'
|
||
if not os.path.exists(info_path):
|
||
... | ... | |
if not os.path.exists(info_path):
|
||
info_path = None
|
||
info_vdr = InfoVdr(info_path)
|
||
self._nfo_content = """<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||
title = info_vdr['T']
|
||
show_subtitles = config.show_subtitles
|
||
if config.guess_episodes:
|
||
episodes_path = '/'.join(self.path.split('/')[:-2]) + '/.episodes'
|
||
if os.path.exists(episodes_path):
|
||
self.is_episode = True
|
||
elif len(self.parent) > 0:
|
||
titleTr = string.lower(title.translate(None, vdrNameIgnore))
|
||
parentTr = string.lower(self.parent.translate(None, vdrNameIgnore))
|
||
if (titleTr.startswith(parentTr) or titleTr.endswith(parentTr) or
|
||
parentTr.startswith(titleTr) or parentTr.endswith(titleTr)):
|
||
self.is_episode = True
|
||
if self.is_episode:
|
||
title = self.parent
|
||
show_subtitles = True
|
||
global episodeMarker
|
||
match = episodeMarker.match(self.name)
|
||
if match:
|
||
self.season = match.group('seasonA')
|
||
self.episode = match.group('episodeA')
|
||
if not self.season:
|
||
self.season = match.group('seasonB')
|
||
self.episode = match.group('episodeB')
|
||
self.season = string.lstrip(self.season, '0')
|
||
self.episode = string.lstrip(self.episode, '0')
|
||
if show_subtitles:
|
||
sub_title = info_vdr['S']
|
||
if len(sub_title.strip()) > 0:
|
||
title += " - "
|
||
if self.season:
|
||
title += str(self.season).zfill(2) + 'x' + str(self.episode).zfill(2) + ' '
|
||
title += sub_title
|
||
elif self.name != '':
|
||
title += " - " + self.name
|
||
if self.is_episode == True:
|
||
self._nfo_content = """<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||
<episodedetails>
|
||
<title>%s</title>
|
||
<plot>%s</plot>
|
||
<season>%s</season>
|
||
<episode>%s</episode>
|
||
</episodedetails>
|
||
""" % (title, info_vdr['D'], self.season, self.episode)
|
||
else:
|
||
self._nfo_content = """<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||
<movie>
|
||
<title>%s</title>
|
||
<plot>%s</plot>
|
||
</movie>
|
||
""" % (info_vdr['T'], info_vdr['D'])
|
||
""" % (title, info_vdr['D'])
|
||
return self._nfo_content
|
||
def size(self):
|
vdrnfofs-0.8.ralf/vdrnfofs/vdrnfofs.py 2013-03-30 22:56:08.107991204 +0100 | ||
---|---|---|
import traceback
|
||
import logging
|
||
import config
|
||
from concatenated_file_reader import *
|
||
from vdr import *
|
||
from filesystemnodes import *
|
||
... | ... | |
elif virtual_file_extension == '.mpg':
|
||
return MpgNode(video_path)
|
||
elif virtual_file_extension == '.nfo':
|
||
return NfoNode(video_path)
|
||
return NfoNode(video_path, video)
|
||
else:
|
||
dir = video + path
|
||
if os.path.isdir(dir):
|
||
... | ... | |
self.video = ''
|
||
self.log = ''
|
||
self.loglevel = 'info'
|
||
self.guess_episode = False
|
||
self.show_subtitles = False
|
||
self.cache = NodeCache()
|
||
def getattr(self, path):
|
||
... | ... | |
logging.basicConfig(filename=self.log, level=getattr(logging, self.loglevel.upper()))
|
||
else:
|
||
logging.basicConfig(level=self.loglevel.upper())
|
||
if self.guess_episodes == None:
|
||
config.guess_episodes = True
|
||
if self.show_subtitles == None:
|
||
config.show_subtitles = True
|
||
logging.info('Starting vdrnfofs')
|
||
VdrNfoFsFile.video_root = self.video
|
||
... | ... | |
fs.parser.add_option(mountopt="video", default='', help="The video directory containing the VDR recordings")
|
||
fs.parser.add_option(mountopt="log", default='', help="The log file (default = console)")
|
||
fs.parser.add_option(mountopt="loglevel", default='info', help="The log level (debug, info, warning or error)")
|
||
fs.parser.add_option(mountopt="guess_episodes", default=False, help="try to guess episodes (title equals parent dir, filename starts with '0x0 ')")
|
||
fs.parser.add_option(mountopt="show_subtitles", default=False, help="add subtitles to title tags in nfo files")
|
||
fs.parse(values=fs, errex=1)
|
||
fs.main()
|
||
vdrnfofs-0.8.ralf/vdrnfofs.egg-info/SOURCES.txt 2013-03-31 14:53:59.662790268 +0200 | ||
---|---|---|
bin/vdrnfofs
|
||
vdrnfofs/__init__.py
|
||
vdrnfofs/concatenated_file_reader.py
|
||
vdrnfofs/config.py
|
||
vdrnfofs/filesystemnodes.py
|
||
vdrnfofs/nodecache.py
|
||
vdrnfofs/vdr.py
|