Package translate :: Package storage :: Module subtitles

[hide private]
[frames] | no frames]

# Source Code for Module translate.storage.subtitles

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2008-2009 Zuza Software Foundation
      5  #
      6  # This file is part of translate.
      7  #
      8  # translate is free software; you can redistribute it and/or modify
      9  # it under the terms of the GNU General Public License as published by
     10  # the Free Software Foundation; either version 2 of the License, or
     11  # (at your option) any later version.
     12  #
     13  # translate is distributed in the hope that it will be useful,
     14  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  # GNU General Public License for more details.
     17  #
     18  # You should have received a copy of the GNU General Public License
     19  # along with translate; if not, write to the Free Software
     20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     21
     22  """Class that manages subtitle files for translation
     23
     24     This class makes use of the subtitle functionality of L{gaupol}
     25     @see: gaupo/agents/open.py::open_main
     26
     27     a patch to gaupol is required to open utf-8 files successfully
     28  """
     29
     30  from StringIO import StringIO
     31  import tempfile
     32  import os
     33
     34  try:
     35      from aeidon import Subtitle
     36      from aeidon import documents
     37      from aeidon.encodings import detect
     38      from aeidon.util import detect_format as determine
     39      from aeidon.files import new
     40      from aeidon.files import MicroDVD, SubStationAlpha, AdvSubStationAlpha, SubRip
     41      from aeidon import newlines
     42  except ImportError:
     43      from gaupol.subtitle import Subtitle
     44      from gaupol import documents
     45      from gaupol.encodings import detect
     46      from gaupol import FormatDeterminer
     47      _determiner = FormatDeterminer()
     48      determine = _determiner.determine
     49      from gaupol.files import new
     50      from gaupol.files import MicroDVD, SubStationAlpha, AdvSubStationAlpha, SubRip
     51      from gaupol.newlines import newlines
     52
     53  from translate.storage import base
     54
     55 -class SubtitleUnit(base.TranslationUnit):
     56      """A subtitle entry that is translatable"""
     57
     58 -    def __init__(self, source=None, encoding="utf_8"):
     59          self._start = None
     60          self._end = None
     61          if source:
     62              self.source = source
     63          super(SubtitleUnit, self).__init__(source)
     64
     65 -    def getnotes(self, origin=None):
     66          if origin in ['programmer', 'developer', 'source code', None]:
     67              return "visible for %d seconds" % self._duration
     68          else:
     69              return ''
     70
     71 -    def getlocations(self):
     72          return ["%s-->%s" % (self._start, self._end)]
     73
     74 -    def getid(self):
     75          return self.getlocations()[0]
     76
     77 -class SubtitleFile(base.TranslationStore):
     78      """A subtitle file"""
     79      UnitClass = SubtitleUnit
     80 -    def __init__(self, inputfile=None, unitclass=UnitClass):
     81          """construct an Subtitle file, optionally reading in from inputfile."""
     82          self.UnitClass = unitclass
     83          base.TranslationStore.__init__(self, unitclass=unitclass)
     84          self.units = []
     85          self.filename = None
     86          self._subtitlefile = None
     87          self._encoding = 'utf_8'
     88          if inputfile is not None:
     89              self._parsefile(inputfile)
     90
     91 -    def __str__(self):
     92          subtitles = []
     93          for unit in self.units:
     94              subtitle = Subtitle()
     95              subtitle.main_text = unit.target or unit.source
     96              subtitle.start = unit._start
     97              subtitle.end = unit._end
     98              subtitles.append(subtitle)
     99          output = StringIO()
    100          self._subtitlefile.write_to_file(subtitles, documents.MAIN, output)
    101          return output.getvalue().encode(self._subtitlefile.encoding)
    102
    103 -    def _parse(self):
    104          try:
    105              self._encoding = detect(self.filename)
    106              if self._encoding == 'ascii':
    107                  self._encoding = 'utf_8'
    108              self._format = determine(self.filename, self._encoding)
    109              self._subtitlefile = new(self._format, self.filename, self._encoding)
    110              for subtitle in self._subtitlefile.read():
    111                  newunit = self.addsourceunit(subtitle.main_text)
    112                  newunit._start = subtitle.start
    113                  newunit._end = subtitle.end
    114                  newunit._duration = subtitle.duration_seconds
    115          except Exception, e:
    116              raise base.ParseError(e)
    117
    118 -    def _parsefile(self, storefile):
    119          if hasattr(storefile, 'name'):
    120              self.filename = storefile.name
    121              storefile.close()
    122          elif hasattr(storefile, 'filename'):
    123              self.filename = storefile.filename
    124              storefile.close()
    125          elif isinstance(storefile, basestring):
    126              self.filename = storefile
    127
    128          if self.filename and os.path.exists(self.filename):
    129              self._parse()
    130          else:
    131              self.parse(storefile.read())
    132
    133      @classmethod
    134 -    def parsefile(cls, storefile):
    135          """parse the given file"""
    136          newstore = cls()
    137          newstore._parsefile(storefile)
    138          return newstore
    139
    140 -    def parse(self, input):
    141          if isinstance(input, basestring):
    142              # Gaupol does not allow parsing from strings
    143              if self.filename:
    144                  tmpfile, tmpfilename = tempfile.mkstemp(suffix=self.filename)
    145              else:
    146                  tmpfile, tmpfilename = tempfile.mkstemp()
    147              tmpfile = open(tmpfilename, 'w')
    148              tmpfile.write(input)
    149              tmpfile.close()
    150              self._parsefile(tmpfilename)
    151              os.remove(tmpfilename)
    152          else:
    153              self._parsefile(input)
    154
    155
    156  ############# format specific classes ###################
    157
    158  # the generic SubtitleFile can adapt to any format, but only the
    159  # specilized classes can be used to construct a new file
    160
    161 -class SubRipFile(SubtitleFile):
    162      """specialized class for SubRipFile's only"""
    163      Name = _("SubRip subtitles file")
    164      Extensions = ['srt']
    165 -    def __init__(self, *args, **kwargs):
    166          super(SubRipFile, self).__init__(*args, **kwargs)
    167          if self._subtitlefile is None:
    168              self._subtitlefile = SubRip(self.filename or '', self._encoding)
    169          if self._subtitlefile.newline is None:
    170              self._subtitlefile.newline = newlines.UNIX
    171
    172 -class MicroDVDFile(SubtitleFile):
    173      """specialized class for SubRipFile's only"""
    174      Name = _("MicroDVD subtitles file")
    175      Extensions = ['sub']
    176 -    def __init__(self, *args, **kwargs):
    177          super(SubRipFile, self).__init__(*args, **kwargs)
    178          if self._subtitlefile is None:
    179              self._subtitlefile = MicroDVD(self.filename or '', self._encoding)
    180          if self._subtitlefile.newline is None:
    181              self._subtitlefile.newline = newlines.UNIX
    182
    183 -class AdvSubStationAlphaFile(SubtitleFile):
    184      """specialized class for SubRipFile's only"""
    185      Name = _("Advanced Substation Alpha subtitles file")
    186      Extensions = ['ass']
    187 -    def __init__(self, *args, **kwargs):
    188          super(SubRipFile, self).__init__(*args, **kwargs)
    189          if self._subtitlefile is None:
    190              self._subtitlefile = AdvSubStationAlpha(self.filename or '', self._encoding)
    191          if self._subtitlefile.newline is None:
    192              self._subtitlefile.newline = newlines.UNIX
    193
    194 -class SubStationAlphaFile(SubtitleFile):
    195      """specialized class for SubRipFile's only"""
    196      Name = _("Substation Alpha subtitles file")
    197      Extensions = ['ssa']
    198 -    def __init__(self, *args, **kwargs):
    199          super(SubRipFile, self).__init__(*args, **kwargs)
    200          if self._subtitlefile is None:
    201              self._subtitlefile = SubStationAlpha(self.filename or '', self._encoding)
    202          if self._subtitlefile.newline is None:
    203              self._subtitlefile.newline = newlines.UNIX
    204