* morituri/common/common.py:
* morituri/common/program.py: * morituri/image/table.py: * morituri/rip/cd.py: * morituri/test/test_common_common.py: * morituri/test/test_image_toc.py: Handle cases where disc_template and track_template are not in the same directory.
This commit is contained in:
11
ChangeLog
11
ChangeLog
@@ -1,3 +1,14 @@
|
||||
2012-11-23 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/common/common.py:
|
||||
* morituri/common/program.py:
|
||||
* morituri/image/table.py:
|
||||
* morituri/rip/cd.py:
|
||||
* morituri/test/test_common_common.py:
|
||||
* morituri/test/test_image_toc.py:
|
||||
Handle cases where disc_template and track_template are not in
|
||||
the same directory.
|
||||
|
||||
2012-11-19 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* morituri/test/test_common_encode.py:
|
||||
|
||||
@@ -21,10 +21,14 @@
|
||||
# along with morituri. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import math
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
from morituri.extern.log import log
|
||||
|
||||
|
||||
SAMPLES_PER_FRAME = 588
|
||||
WORDS_PER_FRAME = SAMPLES_PER_FRAME * 2
|
||||
BYTES_PER_FRAME = SAMPLES_PER_FRAME * 4
|
||||
@@ -334,3 +338,28 @@ def getRealPath(refPath, filePath):
|
||||
return cpath
|
||||
|
||||
raise KeyError("Cannot find file for %r" % filePath)
|
||||
|
||||
def getRelativePath(targetPath, collectionPath):
|
||||
"""
|
||||
Get a relative path from the directory of collectionPath to
|
||||
targetPath.
|
||||
|
||||
Used to determine the path to use in .cue/.m3u files
|
||||
"""
|
||||
log.debug('common', 'getRelativePath: target %r, collection %r' % (
|
||||
targetPath, collectionPath))
|
||||
|
||||
targetDir = os.path.dirname(targetPath)
|
||||
collectionDir = os.path.dirname(collectionPath)
|
||||
if targetDir == collectionDir:
|
||||
log.debug('common',
|
||||
'getRelativePath: target and collection in same dir')
|
||||
return os.path.basename(targetPath)
|
||||
else:
|
||||
rel = os.path.relpath(
|
||||
targetDir + os.path.sep,
|
||||
collectionDir + os.path.sep)
|
||||
log.debug('common',
|
||||
'getRelativePath: target and collection in different dir, %r' %
|
||||
rel)
|
||||
return os.path.join(rel, os.path.basename(targetPath))
|
||||
|
||||
@@ -600,7 +600,7 @@ class Program(log.Loggable):
|
||||
self.debug('write .cue file to %s', cuePath)
|
||||
handle = open(cuePath, 'w')
|
||||
# FIXME: do we always want utf-8 ?
|
||||
handle.write(self.result.table.cue().encode('utf-8'))
|
||||
handle.write(self.result.table.cue(cuePath).encode('utf-8'))
|
||||
handle.close()
|
||||
|
||||
self.cuePath = cuePath
|
||||
|
||||
@@ -503,15 +503,19 @@ class Table(object, log.Loggable):
|
||||
discId1[-1], discId1[-2], discId1[-3],
|
||||
self.getAudioTracks(), discId1, discId2, self.getCDDBDiscId())
|
||||
|
||||
def cue(self, program='Morituri'):
|
||||
def cue(self, cuePath='', program='Morituri'):
|
||||
"""
|
||||
@param cuePath: path to the cue file to be written. If empty,
|
||||
will treat paths as if in current directory.
|
||||
|
||||
|
||||
Dump our internal representation to a .cue file content.
|
||||
"""
|
||||
lines = []
|
||||
|
||||
def writeFile(path):
|
||||
lines.append('FILE "%s" WAVE' % os.path.basename(path))
|
||||
|
||||
targetPath = common.getRelativePath(path, cuePath)
|
||||
lines.append('FILE "%s" WAVE' % targetPath)
|
||||
|
||||
# header
|
||||
main = ['PERFORMER', 'TITLE']
|
||||
|
||||
@@ -58,6 +58,13 @@ filling in the variables and expanding the file extension. Variables are:
|
||||
- %A: album artist
|
||||
- %S: album sort name
|
||||
- %d: disc title
|
||||
- %y: release year
|
||||
|
||||
Paths to track files referenced in .cue and .m3u files will be made
|
||||
relative to the directory of the disc files.
|
||||
|
||||
All files will be created relative to the given output directory.
|
||||
Log files will log the path to tracks relative to this directory.
|
||||
"""
|
||||
|
||||
def addOptions(self):
|
||||
@@ -69,7 +76,9 @@ filling in the variables and expanding the file extension. Variables are:
|
||||
default=default)
|
||||
self.parser.add_option('-O', '--output-directory',
|
||||
action="store", dest="output_directory",
|
||||
help="output directory (defaults to current directory)")
|
||||
help="output directory "
|
||||
"(defaults to absolute path to current directory) "
|
||||
)
|
||||
# FIXME: have a cache of these pickles somewhere
|
||||
self.parser.add_option('-T', '--toc-pickle',
|
||||
action="store", dest="toc_pickle",
|
||||
@@ -107,13 +116,6 @@ filling in the variables and expanding the file extension. Variables are:
|
||||
options.track_template = options.track_template.decode('utf-8')
|
||||
options.disc_template = options.disc_template.decode('utf-8')
|
||||
|
||||
slashCountT = len(options.track_template.split(os.path.sep))
|
||||
slashCountD = len(options.disc_template.split(os.path.sep))
|
||||
if slashCountT != slashCountD:
|
||||
raise command.CommandError(
|
||||
"The number of path separators in the templates " \
|
||||
"should be the same.")
|
||||
|
||||
def do(self, args):
|
||||
prog = program.Program(record=self.getRootCommand().record)
|
||||
runner = task.SyncRunner()
|
||||
@@ -208,14 +210,19 @@ See http://sourceforge.net/tracker/?func=detail&aid=604751&group_id=2171&atid=1
|
||||
# FIXME: turn this into a method
|
||||
|
||||
def ripIfNotRipped(number):
|
||||
self.debug('ripIfNotRipped for track %d' % number)
|
||||
# we can have a previous result
|
||||
trackResult = prog.result.getTrackResult(number)
|
||||
if not trackResult:
|
||||
trackResult = result.TrackResult()
|
||||
prog.result.tracks.append(trackResult)
|
||||
else:
|
||||
self.debug('ripIfNotRipped have trackresult, path %r' %
|
||||
trackResult.filename)
|
||||
|
||||
path = prog.getPath(prog.outdir, self.options.track_template,
|
||||
mbdiscid, number) + '.' + profile.extension
|
||||
self.debug('ripIfNotRipped: path %r' % path)
|
||||
trackResult.number = number
|
||||
|
||||
assert type(path) is unicode, "%r is not unicode" % path
|
||||
@@ -225,6 +232,12 @@ See http://sourceforge.net/tracker/?func=detail&aid=604751&group_id=2171&atid=1
|
||||
|
||||
# FIXME: optionally allow overriding reripping
|
||||
if os.path.exists(path):
|
||||
if path != trackResult.filename:
|
||||
# the path is different (different name/template ?)
|
||||
# but we can copy it
|
||||
self.debug('previous result %r, expected %r' % (
|
||||
trackResult.filename, path))
|
||||
|
||||
self.stdout.write('Verifying track %d of %d: %s\n' % (
|
||||
number, len(itable.tracks),
|
||||
os.path.basename(path).encode('utf-8')))
|
||||
@@ -326,9 +339,10 @@ See http://sourceforge.net/tracker/?func=detail&aid=604751&group_id=2171&atid=1
|
||||
handle.write(u'#EXTM3U\n')
|
||||
|
||||
def writeFile(handle, path, length):
|
||||
u = u'#EXTINF:%d,%s\n' % (length, os.path.basename(path))
|
||||
targetPath = common.getRelativePath(path, m3uPath)
|
||||
u = u'#EXTINF:%d,%s\n' % (length, targetPath)
|
||||
handle.write(u.encode('utf-8'))
|
||||
u = '%s\n' % os.path.basename(path)
|
||||
u = '%s\n' % targetPath
|
||||
handle.write(u.encode('utf-8'))
|
||||
|
||||
|
||||
|
||||
@@ -25,3 +25,14 @@ class FramesTestCase(tcommon.TestCase):
|
||||
class FormatTimeTestCase(tcommon.TestCase):
|
||||
def testFormatTime(self):
|
||||
self.assertEquals(common.formatTime(7202), '02:00:02.000')
|
||||
|
||||
|
||||
class GetRelativePathTestCase(tcommon.TestCase):
|
||||
|
||||
def testRelativeOutputDirectory(self):
|
||||
directory = '.Placebo - Black Market Music (2000)'
|
||||
cue = './' + directory + '/Placebo - Black Market Music (2000)'
|
||||
track = './' + directory + '/01. Placebo - Taste in Men.flac'
|
||||
|
||||
self.assertEquals(common.getRelativePath(track, cue),
|
||||
'01. Placebo - Taste in Men.flac')
|
||||
|
||||
@@ -14,8 +14,9 @@ from morituri.test import common
|
||||
class CureTestCase(common.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__),
|
||||
u'cure.toc'))
|
||||
self.path = os.path.join(os.path.dirname(__file__),
|
||||
u'cure.toc')
|
||||
self.toc = toc.TocFile(self.path)
|
||||
self.toc.parse()
|
||||
self.assertEquals(len(self.toc.table.tracks), 13)
|
||||
|
||||
@@ -85,7 +86,7 @@ class CureTestCase(common.TestCase):
|
||||
self.toc.table.absolutize()
|
||||
cue = self.toc.table.cue()
|
||||
ref = open(os.path.join(os.path.dirname(__file__), 'cure.cue')).read()
|
||||
self.assertEquals(cue, ref)
|
||||
common.diffStrings(cue, ref)
|
||||
|
||||
# we verify it because it has failed in readdisc in the past
|
||||
self.assertEquals(self.toc.table.getAccurateRipURL(),
|
||||
@@ -109,8 +110,9 @@ class CureTestCase(common.TestCase):
|
||||
class BlocTestCase(common.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__),
|
||||
u'bloc.toc'))
|
||||
self.path = os.path.join(os.path.dirname(__file__),
|
||||
u'bloc.toc')
|
||||
self.toc = toc.TocFile(self.path)
|
||||
self.toc.parse()
|
||||
self.assertEquals(len(self.toc.table.tracks), 13)
|
||||
|
||||
@@ -160,8 +162,9 @@ class BlocTestCase(common.TestCase):
|
||||
class BreedersTestCase(common.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__),
|
||||
u'breeders.toc'))
|
||||
self.path = os.path.join(os.path.dirname(__file__),
|
||||
u'breeders.toc')
|
||||
self.toc = toc.TocFile(self.path)
|
||||
self.toc.parse()
|
||||
self.assertEquals(len(self.toc.table.tracks), 13)
|
||||
|
||||
@@ -189,8 +192,9 @@ class BreedersTestCase(common.TestCase):
|
||||
class LadyhawkeTestCase(common.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__),
|
||||
u'ladyhawke.toc'))
|
||||
self.path = os.path.join(os.path.dirname(__file__),
|
||||
u'ladyhawke.toc')
|
||||
self.toc = toc.TocFile(self.path)
|
||||
self.toc.parse()
|
||||
self.assertEquals(len(self.toc.table.tracks), 13)
|
||||
#import code; code.interact(local=locals())
|
||||
|
||||
Reference in New Issue
Block a user