diff --git a/scripts/suboob b/scripts/suboob
new file mode 100755
index 0000000000000000000000000000000000000000..8a7aa4c4e308633d72278c3727ba625e706b8e8a
--- /dev/null
+++ b/scripts/suboob
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim: ft=python et softtabstop=4 cinoptions=4 shiftwidth=4 ts=4 ai
+
+# Copyright(C) 2010-2011 Julien Veyssier
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from weboob.applications.suboob import Suboob
+
+
+if __name__ == '__main__':
+ Suboob.run()
diff --git a/weboob/applications/suboob/__init__.py b/weboob/applications/suboob/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..7030e2509f4937726a0319f7e5887662dbd07d89
--- /dev/null
+++ b/weboob/applications/suboob/__init__.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2010-2011 Julien Veyssier
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from .suboob import Suboob
+
+__all__ = ['Suboob']
diff --git a/weboob/applications/suboob/suboob.py b/weboob/applications/suboob/suboob.py
new file mode 100644
index 0000000000000000000000000000000000000000..04d2bb414c51b1be12d9bf2a5490ea0ad6310ba8
--- /dev/null
+++ b/weboob/applications/suboob/suboob.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2010-2012 Julien Veyssier
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+from __future__ import with_statement
+
+import sys
+
+from weboob.capabilities.subtitle import ICapSubtitle
+from weboob.tools.application.repl import ReplApplication
+from weboob.tools.application.formatters.iformatter import IFormatter, PrettyFormatter
+from weboob.core import CallErrors
+
+
+__all__ = ['Suboob']
+
+
+def sizeof_fmt(num):
+ for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
+ if num < 1024.0:
+ return "%-4.1f%s" % (num, x)
+ num /= 1024.0
+
+
+class SubtitleListFormatter(PrettyFormatter):
+ MANDATORY_FIELDS = ('id', 'name', 'url', 'fps')
+
+ def get_title(self, obj):
+ return obj.name
+
+ def get_description(self, obj):
+ return '(%s fps)' % (obj.fps)
+
+
+class Suboob(ReplApplication):
+ APPNAME = 'suboob'
+ VERSION = '0.f'
+ COPYRIGHT = 'Copyright(C) 2010-2012 Julien Veyssier'
+ DESCRIPTION = "Console application allowing to search for subtitles on various services " \
+ "and download them."
+ SHORT_DESCRIPTION = "search and download subtitles"
+ CAPS = ICapSubtitle
+ EXTRA_FORMATTERS = {'subtitle_list': SubtitleListFormatter
+ }
+ COMMANDS_FORMATTERS = {'search': 'subtitle_list',
+ }
+
+ def complete_getfile(self, text, line, *ignored):
+ args = line.split(' ', 2)
+ if len(args) == 2:
+ return self._complete_object()
+ elif len(args) >= 3:
+ return self.path_completer(args[2])
+
+ def do_getfile(self, line):
+ """
+ getfile ID [FILENAME]
+
+ Get the subtitle or archive file.
+ FILENAME is where to write the file. If FILENAME is '-',
+ the file is written to stdout.
+ """
+ id, dest = self.parse_command_args(line, 2, 1)
+
+ _id, backend_name = self.parse_id(id)
+
+ if dest is None:
+ dest = '%s' % _id
+
+ try:
+ for backend, buf in self.do('get_subtitle_file', _id, backends=backend_name):
+ if buf:
+ if dest == '-':
+ print buf
+ else:
+ try:
+ with open(dest, 'w') as f:
+ f.write(buf)
+ except IOError, e:
+ print >>sys.stderr, 'Unable to write file in "%s": %s' % (dest, e)
+ return 1
+ return
+ except CallErrors, errors:
+ for backend, error, backtrace in errors:
+ self.bcall_error_handler(backend, error, backtrace)
+
+ print >>sys.stderr, 'Subtitle "%s" not found' % id
+ return 3
+
+ def do_search(self, pattern):
+ """
+ search [PATTERN]
+
+ Search subtitles.
+ """
+ self.change_path([u'search'])
+ if not pattern:
+ pattern = None
+
+ self.start_format(pattern=pattern)
+ for backend, subtitle in self.do('iter_subtitles', pattern=pattern):
+ self.cached_format(subtitle)
+ self.flush()
diff --git a/weboob/capabilities/subtitle.py b/weboob/capabilities/subtitle.py
new file mode 100644
index 0000000000000000000000000000000000000000..31c57e001bb17e7a2c9b520f905bb89730fe2abf
--- /dev/null
+++ b/weboob/capabilities/subtitle.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2010-2012 Julien Veyssier
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from .base import IBaseCap, CapBaseObject, Field, StringField, FloatField, \
+ DateField, IntField, UserError
+
+
+__all__ = ['Subtitle', 'ICapSubtitle']
+
+
+class Subtitle(CapBaseObject):
+ """
+ Subtitle object.
+ """
+ name = StringField('Name of subtitle')
+ url = StringField('Direct url to subtitle file')
+ fps = StringField('Framerate of corresponding video')
+
+ def __init__(self, id, name):
+ CapBaseObject.__init__(self, id)
+ self.name = name
+
+
+class ICapSubtitle(IBaseCap):
+ """
+ Subtitle providers.
+ """
+ def iter_subtitles(self, pattern):
+ """
+ Search subtitles and iterate on results.
+
+ :param pattern: pattern to search
+ :type pattern: str
+ :rtype: iter[:class:`Subtitle`]
+ """
+ raise NotImplementedError()
+
+ def get_subtitle(self, _id):
+ """
+ Get a subtitle object from an ID.
+
+ :param _id: ID of subtitle
+ :type _id: str
+ :rtype: :class:`Subtitle`
+ """
+ raise NotImplementedError()
+
+ def get_subtitle_file(self, _id):
+ """
+ Get the content of the subtitle file.
+
+ :param _id: ID of subtitle
+ :type _id: str
+ :rtype: str
+ """
+ raise NotImplementedError()