Revert "Convert docstrings to reStructuredText"
This reverts commit 3b1bd242d0.
This commit is contained in:
@@ -18,9 +18,10 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with whipper. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Reading .cue files.
|
||||
"""
|
||||
Reading .cue files
|
||||
|
||||
.. seealso:: http://digitalx.org/cuesheetsyntax.php
|
||||
See http://digitalx.org/cuesheetsyntax.php
|
||||
"""
|
||||
|
||||
import re
|
||||
@@ -58,25 +59,18 @@ _INDEX_RE = re.compile(r"""
|
||||
|
||||
|
||||
class CueFile(object):
|
||||
"""I represent a .cue file as an object.
|
||||
|
||||
:cvar logCategory:
|
||||
:vartype logCategory:
|
||||
:ivar path:
|
||||
:vartype path:
|
||||
:ivar rems:
|
||||
:vartype rems:
|
||||
:ivar messages:
|
||||
:vartype messages:
|
||||
:ivar leadout:
|
||||
:vartype leadout:
|
||||
:ivar table: the index table.
|
||||
:vartype table: L{table.Table}
|
||||
"""
|
||||
I represent a .cue file as an object.
|
||||
|
||||
@type table: L{table.Table}
|
||||
@ivar table: the index table.
|
||||
"""
|
||||
logCategory = 'CueFile'
|
||||
|
||||
def __init__(self, path):
|
||||
"""
|
||||
@type path: unicode
|
||||
"""
|
||||
assert type(path) is unicode, "%r is not unicode" % path
|
||||
|
||||
self._path = path
|
||||
@@ -157,12 +151,10 @@ class CueFile(object):
|
||||
continue
|
||||
|
||||
def message(self, number, message):
|
||||
"""Add a message about a given line in the cue file.
|
||||
"""
|
||||
Add a message about a given line in the cue file.
|
||||
|
||||
:param number: line number, counting from 0.
|
||||
:type number:
|
||||
:param message:
|
||||
:type message:
|
||||
@param number: line number, counting from 0.
|
||||
"""
|
||||
self._messages.append((number + 1, message))
|
||||
|
||||
@@ -187,24 +179,23 @@ class CueFile(object):
|
||||
return -1
|
||||
|
||||
def getRealPath(self, path):
|
||||
"""Translate the .cue's FILE to an existing path.
|
||||
"""
|
||||
Translate the .cue's FILE to an existing path.
|
||||
|
||||
:param path:
|
||||
:type path: unicode
|
||||
@type path: unicode
|
||||
"""
|
||||
return common.getRealPath(self._path, path)
|
||||
|
||||
|
||||
class File:
|
||||
"""I represent a FILE line in a cue file.
|
||||
|
||||
:ivar path:
|
||||
:vartype path:
|
||||
:ivar format:
|
||||
:vartype format:
|
||||
"""
|
||||
I represent a FILE line in a cue file.
|
||||
"""
|
||||
|
||||
def __init__(self, path, format):
|
||||
"""
|
||||
@type path: unicode
|
||||
"""
|
||||
assert type(path) is unicode, "%r is not unicode" % path
|
||||
|
||||
self.path = path
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with whipper. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Wrap on-disk CD images based on the .cue file.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from whipper.common import encode
|
||||
@@ -31,23 +35,17 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Image(object):
|
||||
"""Wrap on-disk CD images based on the .cue file.
|
||||
|
||||
:ivar path: .cue path.
|
||||
:vartype path: unicode
|
||||
:ivar cue:
|
||||
:vartype cue:
|
||||
:ivar offsets:
|
||||
:vartype offsets:
|
||||
:ivar lengths:
|
||||
:vartype lengths:
|
||||
:ivar table: the Table of Contents for this image.
|
||||
:vartype table: L{table.Table}
|
||||
"""
|
||||
|
||||
@ivar table: The Table of Contents for this image.
|
||||
@type table: L{table.Table}
|
||||
"""
|
||||
logCategory = 'Image'
|
||||
|
||||
def __init__(self, path):
|
||||
"""
|
||||
@type path: unicode
|
||||
@param path: .cue path
|
||||
"""
|
||||
assert type(path) is unicode, "%r is not unicode" % path
|
||||
|
||||
self._path = path
|
||||
@@ -59,22 +57,19 @@ class Image(object):
|
||||
self.table = None
|
||||
|
||||
def getRealPath(self, path):
|
||||
"""Translate the .cue's FILE to an existing path.
|
||||
"""
|
||||
Translate the .cue's FILE to an existing path.
|
||||
|
||||
:param path: .cue path.
|
||||
:type path:
|
||||
@param path: .cue path
|
||||
"""
|
||||
assert type(path) is unicode, "%r is not unicode" % path
|
||||
|
||||
return self.cue.getRealPath(path)
|
||||
|
||||
def setup(self, runner):
|
||||
"""Do initial setup.
|
||||
|
||||
Like figuring out track lengths and constructing the Table of Contents.
|
||||
|
||||
:param runner:
|
||||
:type runner:
|
||||
"""
|
||||
Do initial setup, like figuring out track lengths, and
|
||||
constructing the Table of Contents.
|
||||
"""
|
||||
logger.debug('setup image start')
|
||||
verify = ImageVerifyTask(self)
|
||||
@@ -113,18 +108,8 @@ class Image(object):
|
||||
|
||||
|
||||
class ImageVerifyTask(task.MultiSeparateTask):
|
||||
"""I verify a disk image and get the necessary track lengths.
|
||||
|
||||
:cvar logCategory:
|
||||
:vartype logCategory:
|
||||
:cvar description:
|
||||
:vartype description:
|
||||
:cvar lengths:
|
||||
:vartype lengths:
|
||||
:ivar image:
|
||||
:vartype image:
|
||||
:ivar tasks:
|
||||
:vartype tasks:
|
||||
"""
|
||||
I verify a disk image and get the necessary track lengths.
|
||||
"""
|
||||
|
||||
logCategory = 'ImageVerifyTask'
|
||||
@@ -188,14 +173,8 @@ class ImageVerifyTask(task.MultiSeparateTask):
|
||||
|
||||
|
||||
class ImageEncodeTask(task.MultiSeparateTask):
|
||||
"""I encode a disk image to a different format.
|
||||
|
||||
:ivar image:
|
||||
:vartype image:
|
||||
:ivar tasks:
|
||||
:vartype tasks:
|
||||
:ivar lengths:
|
||||
:vartype lengths:
|
||||
"""
|
||||
I encode a disk image to a different format.
|
||||
"""
|
||||
|
||||
description = "Encoding tracks"
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with whipper. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Wrap Table of Contents."""
|
||||
"""
|
||||
Wrap Table of Contents.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import urllib
|
||||
@@ -51,22 +53,20 @@ CDTEXT_FIELDS = [
|
||||
|
||||
|
||||
class Track:
|
||||
"""I represent a track entry in an Table.
|
||||
"""
|
||||
I represent a track entry in an Table.
|
||||
|
||||
:cvar number: track number (1-based).
|
||||
:vartype number: int
|
||||
:cvar audio: whether the track is audio.
|
||||
:vartype audio: bool
|
||||
:cvar indexes:
|
||||
:vartype indexes: dict of number -> L{Index}
|
||||
:cvar isrc: ISRC code (12 alphanumeric characters).
|
||||
:vartype isrc: str
|
||||
:cvar cdtext: dictionary of CD Text information; see L{CDTEXT_KEYS}.
|
||||
:vartype cdtext: str -> unicode
|
||||
:cvar session:
|
||||
:vartype session:
|
||||
:cvar pre_emphasis: whether track is pre-emphasised.
|
||||
:vartype pre_emphasis: bool
|
||||
@ivar number: track number (1-based)
|
||||
@type number: int
|
||||
@ivar audio: whether the track is audio
|
||||
@type audio: bool
|
||||
@type indexes: dict of number -> L{Index}
|
||||
@ivar isrc: ISRC code (12 alphanumeric characters)
|
||||
@type isrc: str
|
||||
@ivar cdtext: dictionary of CD Text information; see L{CDTEXT_KEYS}.
|
||||
@type cdtext: str -> unicode
|
||||
@ivar pre_emphasis: whether track is pre-emphasised
|
||||
@type pre_emphasis: bool
|
||||
"""
|
||||
|
||||
number = None
|
||||
@@ -88,18 +88,8 @@ class Track:
|
||||
|
||||
def index(self, number, absolute=None, path=None, relative=None,
|
||||
counter=None):
|
||||
"""Index constructor.
|
||||
|
||||
:param number:
|
||||
:type number:
|
||||
:param absolute: (Default value = None)
|
||||
:type absolute:
|
||||
:param path: (Default value = None)
|
||||
:type path: unicode or None
|
||||
:param relative: (Default value = None)
|
||||
:type relative:
|
||||
:param counter: (Default value = None)
|
||||
:type counter:
|
||||
"""
|
||||
@type path: unicode or None
|
||||
"""
|
||||
if path is not None:
|
||||
assert type(path) is unicode, "%r is not unicode" % path
|
||||
@@ -111,20 +101,24 @@ class Track:
|
||||
return self.indexes[number]
|
||||
|
||||
def getFirstIndex(self):
|
||||
"""Get the first chronological index for this track.
|
||||
"""
|
||||
Get the first chronological index for this track.
|
||||
|
||||
Typically this is INDEX 01; but it could be INDEX 00 if there's
|
||||
a pre-gap.
|
||||
"""
|
||||
indexes = sorted(self.indexes.keys())
|
||||
indexes = self.indexes.keys()
|
||||
indexes.sort()
|
||||
return self.indexes[indexes[0]]
|
||||
|
||||
def getLastIndex(self):
|
||||
indexes = sorted(self.indexes.keys())
|
||||
indexes = self.indexes.keys()
|
||||
indexes.sort()
|
||||
return self.indexes[indexes[-1]]
|
||||
|
||||
def getPregap(self):
|
||||
"""Compute the length of the pregap for this track.
|
||||
"""
|
||||
Returns the length of the pregap for this track.
|
||||
|
||||
The pregap is 0 if there is no index 0, and the difference between
|
||||
index 1 and index 0 if there is.
|
||||
@@ -136,21 +130,11 @@ class Track:
|
||||
|
||||
|
||||
class Index:
|
||||
"""I represent an index for the given source.
|
||||
|
||||
:cvar number:
|
||||
:vartype number:
|
||||
:cvar absolute:
|
||||
:vartype absolute:
|
||||
:cvar path:
|
||||
:vartype path: unicode or None
|
||||
:cvar relative:
|
||||
:vartype relative:
|
||||
:cvar counter: counter for the index source; distinguishes between
|
||||
the matching FILE lines in .cue files for example
|
||||
:vartype counter:
|
||||
"""
|
||||
|
||||
@ivar counter: counter for the index source; distinguishes between
|
||||
the matching FILE lines in .cue files for example
|
||||
@type path: unicode or None
|
||||
"""
|
||||
number = None
|
||||
absolute = None
|
||||
path = None
|
||||
@@ -175,18 +159,14 @@ class Index:
|
||||
|
||||
|
||||
class Table(object):
|
||||
"""I represent a table of indexes on a CD.
|
||||
"""
|
||||
I represent a table of indexes on a CD.
|
||||
|
||||
:cvar tracks: tracks on this CD.
|
||||
:vartype tracks: list of L{Track}
|
||||
:cvar leadout:
|
||||
:vartype leadout:
|
||||
:cvar catalog: catalog number.
|
||||
:vartype catalog: str
|
||||
:cvar cdtext:
|
||||
:vartype cdtext: dict of str -> str
|
||||
:cvar mbdiscid:
|
||||
:vartype mbdiscid:
|
||||
@ivar tracks: tracks on this CD
|
||||
@type tracks: list of L{Track}
|
||||
@ivar catalog: catalog number
|
||||
@type catalog: str
|
||||
@type cdtext: dict of str -> str
|
||||
"""
|
||||
|
||||
tracks = None # list of Track
|
||||
@@ -213,23 +193,23 @@ class Table(object):
|
||||
logger.debug('set logName')
|
||||
|
||||
def getTrackStart(self, number):
|
||||
"""Get the start of the given track number's index 1, in CD frames.
|
||||
"""
|
||||
@param number: the track number, 1-based
|
||||
@type number: int
|
||||
|
||||
:param number: the track number, 1-based.
|
||||
:type number: int
|
||||
:returns: the start of the given track number's index 1, in CD frames.
|
||||
:rtype: int
|
||||
@returns: the start of the given track number's index 1, in CD frames
|
||||
@rtype: int
|
||||
"""
|
||||
track = self.tracks[number - 1]
|
||||
return track.getIndex(1).absolute
|
||||
|
||||
def getTrackEnd(self, number):
|
||||
"""Get the end of the given track number.
|
||||
"""
|
||||
@param number: the track number, 1-based
|
||||
@type number: int
|
||||
|
||||
:param number: the track number, 1-based.
|
||||
:type number: int
|
||||
:returns: the end of the given track number (ie index 1 of next track).
|
||||
:rtype: int
|
||||
@returns: the end of the given track number (ie index 1 of next track)
|
||||
@rtype: int
|
||||
"""
|
||||
# default to end of disc
|
||||
end = self.leadout - 1
|
||||
@@ -248,28 +228,25 @@ class Table(object):
|
||||
return end
|
||||
|
||||
def getTrackLength(self, number):
|
||||
"""Get the length if the given track number, in cd frames.
|
||||
"""
|
||||
@param number: the track number, 1-based
|
||||
@type number: int
|
||||
|
||||
:param number: the track number, 1-based.
|
||||
:type number: int
|
||||
:returns: the length of the given track number, in CD frames.
|
||||
:rtype: int
|
||||
@returns: the length of the given track number, in CD frames
|
||||
@rtype: int
|
||||
"""
|
||||
return self.getTrackEnd(number) - self.getTrackStart(number) + 1
|
||||
|
||||
def getAudioTracks(self):
|
||||
"""Get the number of audio tracks on the CD.
|
||||
|
||||
:returns: the number of audio tracks on the CD.
|
||||
:rtype: int
|
||||
"""
|
||||
@returns: the number of audio tracks on the CD
|
||||
@rtype: int
|
||||
"""
|
||||
return len([t for t in self.tracks if t.audio])
|
||||
|
||||
def hasDataTracks(self):
|
||||
"""Tell wheter the disc contains data tracks.
|
||||
|
||||
:returns: whether this disc contains data tracks
|
||||
:rtype: bool
|
||||
"""
|
||||
@returns: whether this disc contains data tracks
|
||||
"""
|
||||
return len([t for t in self.tracks if not t.audio]) > 0
|
||||
|
||||
@@ -282,16 +259,16 @@ class Table(object):
|
||||
return ret
|
||||
|
||||
def getCDDBValues(self):
|
||||
"""Get all CDDB values needed to calculate disc id and lookup URL.
|
||||
"""
|
||||
Get all CDDB values needed to calculate disc id and lookup URL.
|
||||
|
||||
This includes:
|
||||
* CDDB disc id.
|
||||
* number of audio tracks.
|
||||
* offset of index 1 of each track.
|
||||
* length of disc in seconds (including data track).
|
||||
- CDDB disc id
|
||||
- number of audio tracks
|
||||
- offset of index 1 of each track
|
||||
- length of disc in seconds (including data track)
|
||||
|
||||
:returns:
|
||||
:rtype: list of int
|
||||
@rtype: list of int
|
||||
"""
|
||||
result = []
|
||||
|
||||
@@ -343,19 +320,21 @@ class Table(object):
|
||||
return result
|
||||
|
||||
def getCDDBDiscId(self):
|
||||
"""Calculate the CDDB disc ID.
|
||||
"""
|
||||
Calculate the CDDB disc ID.
|
||||
|
||||
:returns: the 8-character hexadecimal disc ID.
|
||||
:rtype: str
|
||||
@rtype: str
|
||||
@returns: the 8-character hexadecimal disc ID
|
||||
"""
|
||||
values = self.getCDDBValues()
|
||||
return "%08x" % values[0]
|
||||
|
||||
def getMusicBrainzDiscId(self):
|
||||
"""Calculate the MusicBrainz disc ID.
|
||||
"""
|
||||
Calculate the MusicBrainz disc ID.
|
||||
|
||||
:returns: the 28-character base64-encoded disc ID.
|
||||
:rtype: str
|
||||
@rtype: str
|
||||
@returns: the 28-character base64-encoded disc ID
|
||||
"""
|
||||
if self.mbdiscid:
|
||||
logger.debug('getMusicBrainzDiscId: returning cached %r'
|
||||
@@ -426,13 +405,10 @@ class Table(object):
|
||||
'https', host, '/cdtoc/attach', '', query, ''))
|
||||
|
||||
def getFrameLength(self, data=False):
|
||||
"""Get the length in frames (excluding HTOA).
|
||||
"""
|
||||
Get the length in frames (excluding HTOA)
|
||||
|
||||
:param data: whether to include the data tracks in the length
|
||||
(Default value = False)
|
||||
:type data:
|
||||
:returns:
|
||||
:rtype:
|
||||
@param data: whether to include the data tracks in the length
|
||||
"""
|
||||
# the 'real' leadout, not offset by 150 frames
|
||||
if data:
|
||||
@@ -447,20 +423,22 @@ class Table(object):
|
||||
return durationFrames
|
||||
|
||||
def duration(self):
|
||||
"""Get the duration in ms for all audio tracks (excluding HTOA)."""
|
||||
"""
|
||||
Get the duration in ms for all audio tracks (excluding HTOA).
|
||||
"""
|
||||
return int(self.getFrameLength() * 1000.0 / common.FRAMES_PER_SECOND)
|
||||
|
||||
def _getMusicBrainzValues(self):
|
||||
"""Get all MusicBrainz values needed to compute disc id and submit URL.
|
||||
"""
|
||||
Get all MusicBrainz values needed to calculate disc id and submit URL.
|
||||
|
||||
This includes:
|
||||
* track number of first track.
|
||||
* number of audio tracks.
|
||||
* leadout of disc.
|
||||
* offset of index 1 of each track.
|
||||
- track number of first track
|
||||
- number of audio tracks
|
||||
- leadout of disc
|
||||
- offset of index 1 of each track
|
||||
|
||||
:returns:
|
||||
:rtype: list of int
|
||||
@rtype: list of int
|
||||
"""
|
||||
# MusicBrainz disc id does not take into account data tracks
|
||||
|
||||
@@ -498,16 +476,14 @@ class Table(object):
|
||||
return result
|
||||
|
||||
def cue(self, cuePath='', program='whipper'):
|
||||
"""Dump our internal representation to a .cue file content.
|
||||
|
||||
:param cuePath: path to the cue file to be written. If empty,
|
||||
"""
|
||||
@param cuePath: path to the cue file to be written. If empty,
|
||||
will treat paths as if in current directory.
|
||||
(Default value = '')
|
||||
:type cuePath:
|
||||
:param program: (Default value = 'whipper')
|
||||
:type program:
|
||||
:returns:
|
||||
:rtype: C{unicode}
|
||||
|
||||
|
||||
Dump our internal representation to a .cue file content.
|
||||
|
||||
@rtype: C{unicode}
|
||||
"""
|
||||
logger.debug('generating .cue for cuePath %r', cuePath)
|
||||
|
||||
@@ -567,7 +543,8 @@ class Table(object):
|
||||
if not track.audio:
|
||||
continue
|
||||
|
||||
indexes = sorted(track.indexes.keys())
|
||||
indexes = track.indexes.keys()
|
||||
indexes.sort()
|
||||
|
||||
wroteTrack = False
|
||||
|
||||
@@ -619,7 +596,7 @@ class Table(object):
|
||||
# handle any other INDEX 00 after its TRACK
|
||||
lines.append(" INDEX "
|
||||
"%02d %s" % (0, common.framesToMSF(
|
||||
index00.relative)))
|
||||
index00.relative)))
|
||||
|
||||
if number > 0:
|
||||
# index 00 is output after TRACK up above
|
||||
@@ -634,8 +611,8 @@ class Table(object):
|
||||
# methods that modify the table
|
||||
|
||||
def clearFiles(self):
|
||||
"""Clear all file backings.
|
||||
|
||||
"""
|
||||
Clear all file backings.
|
||||
Resets indexes paths and relative offsets.
|
||||
"""
|
||||
# FIXME: do a loop over track indexes better, with a pythonic
|
||||
@@ -657,23 +634,15 @@ class Table(object):
|
||||
break
|
||||
|
||||
def setFile(self, track, index, path, length, counter=None):
|
||||
"""Set the given file as the source from the given index on.
|
||||
|
||||
"""
|
||||
Sets the given file as the source from the given index on.
|
||||
Will loop over all indexes that fall within the given length,
|
||||
to adjust the path.
|
||||
|
||||
Assumes all indexes have an absolute offset and will raise if not.
|
||||
|
||||
:param track:
|
||||
:type track: C{int}
|
||||
:param index:
|
||||
:type index: C{int}
|
||||
:param path:
|
||||
:type path:
|
||||
:param length:
|
||||
:type length:
|
||||
:param counter: (Default value = None)
|
||||
:type counter:
|
||||
@type track: C{int}
|
||||
@type index: C{int}
|
||||
"""
|
||||
logger.debug('setFile: track %d, index %d, path %r, '
|
||||
'length %r, counter %r', track, index, path, length,
|
||||
@@ -701,8 +670,8 @@ class Table(object):
|
||||
break
|
||||
|
||||
def absolutize(self):
|
||||
"""Calculate absolute offsets on indexes as much as possible.
|
||||
|
||||
"""
|
||||
Calculate absolute offsets on indexes as much as possible.
|
||||
Only possible for as long as tracks draw from the same file.
|
||||
"""
|
||||
t = self.tracks[0].number
|
||||
@@ -739,14 +708,12 @@ class Table(object):
|
||||
break
|
||||
|
||||
def merge(self, other, session=2):
|
||||
"""Merge the given table at the end.
|
||||
"""
|
||||
Merges the given table at the end.
|
||||
The other table is assumed to be from an additional session,
|
||||
|
||||
The other table is assumed to be from an additional session.
|
||||
|
||||
:param other:
|
||||
:type other: L{Table}
|
||||
:param session: (Default value = 2)
|
||||
:type session:
|
||||
@type other: L{Table}
|
||||
"""
|
||||
gap = self._getSessionGap(session)
|
||||
|
||||
@@ -791,15 +758,14 @@ class Table(object):
|
||||
# lookups
|
||||
|
||||
def getNextTrackIndex(self, track, index):
|
||||
"""Return the next track and index.
|
||||
"""
|
||||
Return the next track and index.
|
||||
|
||||
:param track: track number, 1-based.
|
||||
:type track:
|
||||
:param index:
|
||||
:type index:
|
||||
:raises IndexError: on last index.
|
||||
:returns:
|
||||
:rtype: tuple of (int, int)
|
||||
@param track: track number, 1-based
|
||||
|
||||
@raises IndexError: on last index
|
||||
|
||||
@rtype: tuple of (int, int)
|
||||
"""
|
||||
t = self.tracks[track - 1]
|
||||
indexes = t.indexes.keys()
|
||||
@@ -821,9 +787,9 @@ class Table(object):
|
||||
# various tests for types of Table
|
||||
|
||||
def hasTOC(self):
|
||||
"""Check if the Table has a complete TOC.
|
||||
|
||||
A TOC is a list of all tracks and their Index 01, with absolute
|
||||
"""
|
||||
Check if the Table has a complete TOC.
|
||||
a TOC is a list of all tracks and their Index 01, with absolute
|
||||
offsets, as well as the leadout.
|
||||
"""
|
||||
if not self.leadout:
|
||||
@@ -841,10 +807,9 @@ class Table(object):
|
||||
return True
|
||||
|
||||
def accuraterip_ids(self):
|
||||
"""Compute both AccurateRip disc ids.
|
||||
|
||||
The ids are returned as a tuple of 8-char hexadecimal
|
||||
strings (discid1, discid2).
|
||||
"""
|
||||
returns both AccurateRip disc ids as a tuple of 8-char
|
||||
hexadecimal strings (discid1, discid2)
|
||||
"""
|
||||
# AccurateRip does not take into account data tracks,
|
||||
# but does count the data track to determine the leadout offset
|
||||
@@ -877,7 +842,9 @@ class Table(object):
|
||||
)
|
||||
|
||||
def canCue(self):
|
||||
"""Check if this table can be used to generate a .cue file."""
|
||||
"""
|
||||
Check if this table can be used to generate a .cue file
|
||||
"""
|
||||
if not self.hasTOC():
|
||||
logger.debug('No TOC, cannot cue')
|
||||
return False
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with whipper. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Reading .toc files.
|
||||
"""
|
||||
Reading .toc files
|
||||
|
||||
The .toc file format is described in the man page of cdrdao.
|
||||
The .toc file format is described in the man page of cdrdao
|
||||
"""
|
||||
|
||||
import re
|
||||
@@ -92,40 +93,29 @@ _INDEX_RE = re.compile(r"""
|
||||
|
||||
|
||||
class Sources:
|
||||
"""I represent the list of sources used in the .toc file.
|
||||
|
||||
"""
|
||||
I represent the list of sources used in the .toc file.
|
||||
Each SILENCE and each FILE is a source.
|
||||
If the filename for FILE doesn't change, the counter is not increased.
|
||||
|
||||
ivar sources:
|
||||
vartype sources:
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._sources = []
|
||||
|
||||
def append(self, counter, offset, source):
|
||||
"""Append tuple containing source information to sources.
|
||||
|
||||
This method also logs the event.
|
||||
|
||||
:param counter: the source counter; updates for each different
|
||||
data source (silence or different file path).
|
||||
:type counter: int
|
||||
:param offset: the absolute disc offset where this source starts.
|
||||
:type offset:
|
||||
:param source:
|
||||
:type source:
|
||||
"""
|
||||
@param counter: the source counter; updates for each different
|
||||
data source (silence or different file path)
|
||||
@type counter: int
|
||||
@param offset: the absolute disc offset where this source starts
|
||||
"""
|
||||
logger.debug('Appending source, counter %d, abs offset %d, '
|
||||
'source %r' % (counter, offset, source))
|
||||
self._sources.append((counter, offset, source))
|
||||
|
||||
def get(self, offset):
|
||||
"""Retrieve the source used at the given offset.
|
||||
|
||||
:param offset:
|
||||
:type offset:
|
||||
"""
|
||||
Retrieve the source used at the given offset.
|
||||
"""
|
||||
for i, (c, o, s) in enumerate(self._sources):
|
||||
if offset < o:
|
||||
@@ -134,10 +124,8 @@ class Sources:
|
||||
return self._sources[-1]
|
||||
|
||||
def getCounterStart(self, counter):
|
||||
"""Retrieve the absolute offset of the first source for this counter.
|
||||
|
||||
:param counter:
|
||||
:type counter:
|
||||
"""
|
||||
Retrieve the absolute offset of the first source for this counter
|
||||
"""
|
||||
for i, (c, o, s) in enumerate(self._sources):
|
||||
if c == counter:
|
||||
@@ -147,21 +135,11 @@ class Sources:
|
||||
|
||||
|
||||
class TocFile(object):
|
||||
"""I represent a .toc file.
|
||||
|
||||
:ivar path:
|
||||
:vartype path: unicode
|
||||
:ivar messages:
|
||||
:vartype messages:
|
||||
:ivar table:
|
||||
:vartype table:
|
||||
:ivar logName:
|
||||
:vartype logName:
|
||||
:ivar sources:
|
||||
:vartype sources:
|
||||
"""
|
||||
|
||||
def __init__(self, path):
|
||||
"""
|
||||
@type path: unicode
|
||||
"""
|
||||
assert type(path) is unicode, "%r is not unicode" % path
|
||||
self._path = path
|
||||
self._messages = []
|
||||
@@ -400,22 +378,17 @@ class TocFile(object):
|
||||
logger.debug('parse: leadout: %r', self.table.leadout)
|
||||
|
||||
def message(self, number, message):
|
||||
"""Add a message about a given line in the cue file.
|
||||
"""
|
||||
Add a message about a given line in the cue file.
|
||||
|
||||
:param number: line number, counting from 0.
|
||||
:type number:
|
||||
:param message:
|
||||
:type message:
|
||||
@param number: line number, counting from 0.
|
||||
"""
|
||||
self._messages.append((number + 1, message))
|
||||
|
||||
def getTrackLength(self, track):
|
||||
"""Compute the length of the given track.
|
||||
|
||||
The lenght is computed from its INDEX 01 to the next track's INDEX 01.
|
||||
|
||||
:param track:
|
||||
:type track:
|
||||
"""
|
||||
Returns the length of the given track, from its INDEX 01 to the next
|
||||
track's INDEX 01
|
||||
"""
|
||||
# returns track length in frames, or -1 if can't be determined and
|
||||
# complete file should be assumed
|
||||
@@ -437,26 +410,26 @@ class TocFile(object):
|
||||
return -1
|
||||
|
||||
def getRealPath(self, path):
|
||||
"""Translate the .toc's FILE to an existing path.
|
||||
"""
|
||||
Translate the .toc's FILE to an existing path.
|
||||
|
||||
:param path:
|
||||
:type path: unicode
|
||||
@type path: unicode
|
||||
"""
|
||||
return common.getRealPath(self._path, path)
|
||||
|
||||
|
||||
class File:
|
||||
"""I represent a FILE line in a .toc file.
|
||||
|
||||
:ivar path:
|
||||
:vartype path: C{unicode}
|
||||
:ivar start: starting point for the track in this file, in frames.
|
||||
:vartype start: C{int}
|
||||
:ivar length: length for the track in this file, in frames.
|
||||
:vartype length:
|
||||
"""
|
||||
I represent a FILE line in a .toc file.
|
||||
"""
|
||||
|
||||
def __init__(self, path, start, length):
|
||||
"""
|
||||
@type path: C{unicode}
|
||||
@type start: C{int}
|
||||
@param start: starting point for the track in this file, in frames
|
||||
@param length: length for the track in this file, in frames
|
||||
"""
|
||||
assert type(path) is unicode, "%r is not unicode" % path
|
||||
|
||||
self.path = path
|
||||
|
||||
Reference in New Issue
Block a user