diff options
author | etobi <git@e-tobi.net> | 2011-09-30 22:55:10 +0200 |
---|---|---|
committer | etobi <git@e-tobi.net> | 2011-09-30 22:55:10 +0200 |
commit | ef9d11bd14ada624435bc5df5fec230a71c9cc6d (patch) | |
tree | 2bb7bc05aadf441363e634a6f140fe789287b7ce | |
download | vdrnfofs-0.6.tar.gz vdrnfofs-0.6.tar.bz2 |
Initial commit (version 0.6)v0.6
44 files changed, 766 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..7e63661 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,29 @@ +Copyright 2010 Tobias Grimm <vdr@e-tobi.net> All rights reserved. + +Software License Agreement (BSD License) + +Redistribution and use of this software in source and binary forms, with or +without modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author/copyright holder nor the names of contributors may + be used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. @@ -0,0 +1 @@ +TODO @@ -0,0 +1 @@ +TODO diff --git a/bin/vdrnfofs b/bin/vdrnfofs new file mode 100755 index 0000000..60d176c --- /dev/null +++ b/bin/vdrnfofs @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +import sys +from vdrnfofs import vdrnfofs + +if __name__ == '__main__': + vdrnfofs.main() diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..63145d2 --- /dev/null +++ b/setup.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os +import re + +from distutils.core import setup +from distutils.file_util import copy_file +from distutils.command.build_py import build_py +from distutils.command.install_data import install_data + +from glob import glob +from subprocess import check_call + +setup ( + name='vdrnfofs', + version='1.0', + maintainer = "Tobias Grimm", + maintainer_email = "vdr@e.tobi.net", + description = "Access VDR recordings as mpg and nfo files", + license = "GNU GPL v2", + scripts = ['bin/vdrnfofs'], + packages = ['vdrnfofs'], +) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/__init__.py diff --git a/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/001.vdr b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/001.vdr new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/001.vdr @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/002.vdr b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/002.vdr new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/002.vdr @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/003.vdr b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/003.vdr new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/003.vdr @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/004.vdr b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/004.vdr new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/004.vdr @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/info.vdr b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/info.vdr new file mode 100644 index 0000000..08787fc --- /dev/null +++ b/tests/sample_video_dir/folder/sample1/2008-03-28.20.13.99.99.rec/info.vdr @@ -0,0 +1,6 @@ +C S19.2E-1-1101-28112 +E 6345 1189982700 18900 4E 10 +T Movie Title +S Movie Subtitle +D A movie about something +X 2 03 deu stereo diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/001.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/001.vdr new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/001.vdr @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/002.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/002.vdr new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/002.vdr @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/003.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/003.vdr new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/003.vdr @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/004.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/004.vdr new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/004.vdr @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/info.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/info.vdr new file mode 100644 index 0000000..08787fc --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.98.rec/info.vdr @@ -0,0 +1,6 @@ +C S19.2E-1-1101-28112 +E 6345 1189982700 18900 4E 10 +T Movie Title +S Movie Subtitle +D A movie about something +X 2 03 deu stereo diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/001.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/001.vdr new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/001.vdr @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/002.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/002.vdr new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/002.vdr @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/003.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/003.vdr new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/003.vdr @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/004.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/004.vdr new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/004.vdr @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/info.vdr b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/info.vdr new file mode 100644 index 0000000..08787fc --- /dev/null +++ b/tests/sample_video_dir/folder/sample2/2008-03-28.20.13.99.99.rec/info.vdr @@ -0,0 +1,6 @@ +C S19.2E-1-1101-28112 +E 6345 1189982700 18900 4E 10 +T Movie Title +S Movie Subtitle +D A movie about something +X 2 03 deu stereo diff --git a/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00001.ts b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00001.ts new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00001.ts @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00002.ts b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00002.ts new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00002.ts @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00003.ts b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00003.ts new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00003.ts @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00004.ts b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00004.ts new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/00004.ts @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/info b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/info new file mode 100644 index 0000000..08787fc --- /dev/null +++ b/tests/sample_video_dir/sample-vdr1.7/2008-03-28.20.13.99.99.rec/info @@ -0,0 +1,6 @@ +C S19.2E-1-1101-28112 +E 6345 1189982700 18900 4E 10 +T Movie Title +S Movie Subtitle +D A movie about something +X 2 03 deu stereo diff --git a/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/001.vdr b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/001.vdr new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/001.vdr @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/002.vdr b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/002.vdr new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/002.vdr @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/003.vdr b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/003.vdr new file mode 100644 index 0000000..6a537b5 --- /dev/null +++ b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/003.vdr @@ -0,0 +1 @@ +1234567890
\ No newline at end of file diff --git a/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/004.vdr b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/004.vdr new file mode 100644 index 0000000..c76a964 --- /dev/null +++ b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/004.vdr @@ -0,0 +1 @@ +abcdefghij
\ No newline at end of file diff --git a/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/info.vdr b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/info.vdr new file mode 100644 index 0000000..08787fc --- /dev/null +++ b/tests/sample_video_dir/sample/2008-03-28.20.13.99.99.rec/info.vdr @@ -0,0 +1,6 @@ +C S19.2E-1-1101-28112 +E 6345 1189982700 18900 4E 10 +T Movie Title +S Movie Subtitle +D A movie about something +X 2 03 deu stereo diff --git a/tests/syslog.py b/tests/syslog.py new file mode 100644 index 0000000..abadaa2 --- /dev/null +++ b/tests/syslog.py @@ -0,0 +1,2 @@ +def syslog(*arg): + raise diff --git a/tests/test_all b/tests/test_all new file mode 100755 index 0000000..02ab99f --- /dev/null +++ b/tests/test_all @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os +import sys +import unittest + +def suite(): + suite = unittest.TestSuite() + for _, _, files in os.walk('.'): + for name in filter(is_test, files): + tests = unittest.defaultTestLoader.loadTestsFromName(name[:-3]) + suite.addTests(tests) + return suite + +def is_test(filename): + return filename.startswith('test_') and filename.endswith('.py') + +if __name__ == "__main__": + sys.path.insert(0, '.') + unittest.main(defaultTest="suite") diff --git a/tests/test_dir.py b/tests/test_dir.py new file mode 100644 index 0000000..e7562f0 --- /dev/null +++ b/tests/test_dir.py @@ -0,0 +1,40 @@ +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys +import os +import unittest +import xml.etree.ElementTree + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from vdrnfofs.vdrnfofs import * + +class TestDir(unittest.TestCase): + def setUp(self): + self.video = self.video_dir = os.path.abspath(os.path.dirname(__file__) + '/sample_video_dir') + + def test_not_existing(self): + node = get_node(self.video, '/does_not_exist') + self.assertEqual(None, node) + + def test_content(self): + node = get_node(self.video, '/') + self.assertEqual(5, len(node.content())) + diff --git a/tests/test_gettattr.py b/tests/test_gettattr.py new file mode 100644 index 0000000..7bae140 --- /dev/null +++ b/tests/test_gettattr.py @@ -0,0 +1,38 @@ +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys +import os +import unittest +import stat + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from vdrnfofs.vdrnfofs import * + +class TestPathToNodeMapping(unittest.TestCase): + def setUp(self): + self.fs = VdrNfoFs() + self.fs.video = self.video_dir = os.path.abspath(os.path.dirname(__file__) + '/sample_video_dir') + + def test_root(self): + attr = self.fs.getattr('/') + self.assertEqual(stat.S_IFDIR | 0755, attr.st_mode) + self.assertEqual(2 + 5, attr.st_nlink) diff --git a/tests/test_mpg.py b/tests/test_mpg.py new file mode 100644 index 0000000..397b5fe --- /dev/null +++ b/tests/test_mpg.py @@ -0,0 +1,46 @@ +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys +import os +import unittest +import xml.etree.ElementTree + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from vdrnfofs.vdrnfofs import * + +class TestMpg(unittest.TestCase): + def setUp(self): + self.video = self.video_dir = os.path.abspath(os.path.dirname(__file__) + '/sample_video_dir') + + def test_not_existing(self): + node = get_node(self.video, '/does_not_exist_2008-03-28.20.13.99.99.rec.mpg') + self.assertEqual(None, node) + + def test_mpg(self): + node = get_node(self.video, '/sample_2008-03-28.20.13.99.99.rec.mpg') + self.assertEqual(40, node.size()) + self.assertEqual('1234567890abcdefghij1234567890abcdefghij', node.read(0, 4096)) + + def test_mpg_new(self): + node = get_node(self.video, '/sample-vdr1.7_2008-03-28.20.13.99.99.rec.mpg') + self.assertEqual(40, node.size()) + self.assertEqual('1234567890abcdefghij1234567890abcdefghij', node.read(0, 4096)) + diff --git a/tests/test_nfo.py b/tests/test_nfo.py new file mode 100644 index 0000000..e7107a3 --- /dev/null +++ b/tests/test_nfo.py @@ -0,0 +1,47 @@ +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys +import os +import unittest +import xml.etree.ElementTree + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from vdrnfofs.vdrnfofs import * + +class TestNfo(unittest.TestCase): + def setUp(self): + self.video = self.video_dir = os.path.abspath(os.path.dirname(__file__) + '/sample_video_dir') + + def test_not_existing(self): + node = get_node(self.video, '/does_not_exist_2008-03-28.20.13.99.99.rec.nfo') + self.assertEqual(None, node) + + def test_nfo(self): + node = get_node(self.video, '/sample_2008-03-28.20.13.99.99.rec.nfo') + nfo = xml.etree.ElementTree.fromstring(node.read(0, 4096)) + self.assertEqual('Movie Title', nfo.find('title').text) + self.assertEqual('A movie about something', nfo.find('plot').text) + + def test_nfo_new(self): + node = get_node(self.video, '/sample-vdr1.7_2008-03-28.20.13.99.99.rec.nfo') + nfo = xml.etree.ElementTree.fromstring(node.read(0, 4096)) + self.assertEqual('Movie Title', nfo.find('title').text) + self.assertEqual('A movie about something', nfo.find('plot').text) diff --git a/tests/test_path_to_node_mapping.py b/tests/test_path_to_node_mapping.py new file mode 100644 index 0000000..59f3515 --- /dev/null +++ b/tests/test_path_to_node_mapping.py @@ -0,0 +1,45 @@ +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys +import os +import unittest + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from vdrnfofs.vdrnfofs import * + +class TestPathToNodeMapping(unittest.TestCase): + def setUp(self): + self.video = self.video_dir = os.path.abspath(os.path.dirname(__file__) + '/sample_video_dir') + + def test_root(self): + node = get_node(self.video, '/') + self.assertEqual('', node.file_system_name) + self.assertEqual(self.video, node.path) + + def test_subdir(self): + node = get_node(self.video, '/folder') + self.assertEqual('folder', node.file_system_name) + self.assertEqual(self.video + '/folder', node.path) + + def test_mpg(self): + node = get_node(self.video, '/sample_2008-03-28.20.13.99.99.rec.mpg') + self.assertEqual('sample_2008-03-28.20.13.99.99.rec.mpg', node.file_system_name) + self.assertEqual(self.video + '/sample/2008-03-28.20.13.99.99.rec', node.path) diff --git a/vdrnfofs/__init__.py b/vdrnfofs/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/vdrnfofs/__init__.py diff --git a/vdrnfofs/concatenated_file_reader.py b/vdrnfofs/concatenated_file_reader.py new file mode 100644 index 0000000..9f05ebd --- /dev/null +++ b/vdrnfofs/concatenated_file_reader.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os + +class ConcatenatedFileReader: + def __init__(self, filenames): + self.files = [(f, os.path.getsize(f)) for f in filenames] + self.current_filename = None + self.current_file = None + + def read(self, offset, size): + buffer = "" + ptr = offset + while (len(buffer) < size): + (filename, file_offset) = self.filename_from_offset(ptr) + if filename: + if (self.current_filename != filename): + if self.current_file: + self.current_file.close() + self.current_filename = filename + self.current_file = open(filename, 'r') + self.current_file.seek(file_offset) + buffer += self.current_file.read(size - len(buffer)) + ptr = offset + len(buffer) + else: + break + return buffer + + def release(self): + if self.current_file: + self.current_file.close() + + def filename_from_offset(self, offset): + for (filename, size) in self.files: + if offset >= size: + offset -= size + else: + return (filename, offset) + return (None, 0) diff --git a/vdrnfofs/filesystemnodes.py b/vdrnfofs/filesystemnodes.py new file mode 100644 index 0000000..6902d9f --- /dev/null +++ b/vdrnfofs/filesystemnodes.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import glob +import os +import fuse +import stat + +from concatenated_file_reader import * +from vdr import * + +class NodeAttributes(fuse.Stat): + def __init__(self): + self.st_mode = 0 + self.st_ino = 0 + self.st_dev = 0 + self.st_nlink = 0 + self.st_uid = 0 + self.st_gid = 0 + self.st_size = 0 + self.st_atime = 0 + self.st_mtime = 0 + self.st_ctime = 0 + +class MpgNode: + def __init__(self, path): + self.path = os.path.normpath(path) + self.mpeg_files = glob.glob(path + '/[0-9]*.vdr') + if not self.mpeg_files: + self.mpeg_files = glob.glob(path + '/[0-9]*.ts') + self.mpeg_files.sort() + self.file_system_name = os.path.basename(os.path.abspath(path + '/..')) + '_' + os.path.basename(path) + '.mpg' + self.reader = ConcatenatedFileReader(self.mpeg_files) + + def size(self): + size = 0 + for file in self.mpeg_files: + size += os.path.getsize(file) + return size + + def read(self, offset, size): + return self.reader.read(offset, size) + + def release(self): + return self.reader.release() + + def get_stat(self): + attr = NodeAttributes() + attr.st_mode = stat.S_IFREG | 644 + attr.st_nlink = 1 + attr.st_size = self.size() + return attr + + +class NfoNode: + def __init__(self, path): + self.path = os.path.normpath(path) + self.file_system_name = os.path.basename(os.path.abspath(path + '/..')) + '_' + os.path.basename(path) + '.nfo' + if os.path.exists(path + '/info.vdr'): + info_vdr = InfoVdr(path + '/info.vdr') + elif os.path.exists(path + '/info'): + info_vdr = InfoVdr(path + '/info') + else: + info_vdr = InfoVdr() + 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']) + + def size(self): + return len(self.nfo_content) + + def read(self, offset, size): + return self.nfo_content[offset:offset+size] + + def get_stat(self): + attr = NodeAttributes() + attr.st_mode = stat.S_IFREG | 644 + attr.st_nlink = 1 + attr.st_size = self.size() + return attr + + +class DirNode: + def __init__(self, path): + self.path = os.path.normpath(path) + self.file_system_name = os.path.basename(path) + self.cache = [] + + def content(self): + if not self.cache: + for entry in os.listdir(self.path): + entry = self.path + '/' + entry + if self.is_sub_folder(entry): + self.cache.append(DirNode(entry)) + for recording in glob.glob(entry + '/*.rec'): + if os.path.exists(recording + '/info.vdr') or os.path.exists(recording + '/info'): + self.cache.append(MpgNode(recording)) + self.cache.append(NfoNode(recording)) + return self.cache + + def is_sub_folder(self, dir): + if not os.path.isdir(dir): + return False + if dir.endswith('.rec'): + return False + for entry in os.listdir(dir): + if not entry.endswith('.rec'): + return True + return False + + def get_stat(self): + attr = NodeAttributes() + attr.st_mode = stat.S_IFDIR | 0755 + attr.st_nlink = 2 + len(self.content()) + return attr diff --git a/vdrnfofs/vdr.py b/vdrnfofs/vdr.py new file mode 100644 index 0000000..b3c2311 --- /dev/null +++ b/vdrnfofs/vdr.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +class InfoVdr: + def __init__(self, filename = None): + self.values = {'T' : 'Unknown', 'D': 'No Description'} + if filename: + file = open(filename, 'r') + for line in file: + line = line.rstrip("\r\n") + self.values[line[0]] = line[2:] + + def __getitem__(self, key): + return self.values[key] if self.values.has_key(key) else '' diff --git a/vdrnfofs/vdrnfofs.py b/vdrnfofs/vdrnfofs.py new file mode 100644 index 0000000..dc6deb3 --- /dev/null +++ b/vdrnfofs/vdrnfofs.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +# +# VDR-NFO-FS creates a file system for VDR recordings, which maps each +# recording to a single mpg-file and nfo-file containing some meta data. +# +# Copyright (C) 2010 - 2011 by Tobias Grimm +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os +import stat +import errno +import sys +import fuse +import syslog + +from concatenated_file_reader import * +from vdr import * +from filesystemnodes import * + +fuse.fuse_python_api = (0, 2) + +def get_node(video, path): + virtual_path, virtual_file_extension = os.path.splitext(path) + if virtual_file_extension in ['.mpg', '.nfo']: + p = virtual_path.rfind('_') + if p > 0: + video_path = video + '/' + virtual_path[0:p] + '/' + virtual_path[p+1:] + if not os.path.isdir(video_path): + return None + elif virtual_file_extension == '.mpg': + return MpgNode(video_path) + elif virtual_file_extension == '.nfo': + return NfoNode(video_path) + else: + if os.path.isdir(video + '/' + path): + return DirNode(video + path) + return None + +class VdrNfoFsFile: + def __init__(self, path, flags, *mode): + self.path = path + self.node = get_node(VdrNfoFsFile.video_root, path) + + def read(self, size, offset): + try: + if not self.node: + return -errno.ENOENT + return self.node.read(offset, size) + except: + syslog.syslog('VdrFuseFs: Unexpected error for read(%s)' % self.path) + + def release(self, flags): + self.node.release() + +# def write(self, buf, offset): +# return 0 + +# def _fflush(self): +# if 'w' in self.file.mode or 'a' in self.file.mode: +# self.file.flush() + +# def fsync(self, isfsyncfile): + +# def flush(self): + +# def fgetattr(self): +# return 0 + +# def ftruncate(self, len): + +# def lock(self, cmd, owner, **kw): + + +class VdrNfoFs(fuse.Fuse): + def __init__(self, *args, **kw): + fuse.Fuse.__init__(self, *args, **kw) + self.video = "" + + def getattr(self, path): + try: + node = get_node(self.video, path) + if node: + return node.get_stat() + return -errno.ENOENT + except: + syslog.syslog('VdrFuseFs: Unexpected error for getattr(%s): %s' % path) + + def readdir(self, path, offset): + try: + yield fuse.Direntry('.') + yield fuse.Direntry('..') + node = get_node(self.video, path) + if node: + for item in node.content(): + yield fuse.Direntry(item.file_system_name) + except: + syslog.syslog('VdrFuseFs: Unexpected error for readdir(%s)' % path) + + def main(self, *a, **kw): + VdrNfoFsFile.video_root = self.video + self.file_class = VdrNfoFsFile + return fuse.Fuse.main(self, *a, **kw) + +def main(): + usage = "\nVDR-NFO-FS - access VDR recordings as mpg and nfo files\n" + usage += fuse.Fuse.fusage + + version = "%prog " + fuse.__version__ + + fs = VdrNfoFs(version=version, usage=usage, dash_s_do='setsingle') + fs.parser.add_option(mountopt="video", default='', help="The video directory containing the VDR recordings") + fs.parse(values=fs, errex=1) + fs.main() + +if __name__ == '__main__': + main() |