* 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:
Thomas Vander Stichele
2012-11-22 23:20:44 +00:00
parent d0435dc2ab
commit 9b4e653ae4
7 changed files with 96 additions and 23 deletions

View File

@@ -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> 2012-11-19 Thomas Vander Stichele <thomas at apestaart dot org>
* morituri/test/test_common_encode.py: * morituri/test/test_common_encode.py:

View File

@@ -21,10 +21,14 @@
# along with morituri. If not, see <http://www.gnu.org/licenses/>. # along with morituri. If not, see <http://www.gnu.org/licenses/>.
import os import os
import os.path
import math import math
import tempfile import tempfile
import shutil import shutil
from morituri.extern.log import log
SAMPLES_PER_FRAME = 588 SAMPLES_PER_FRAME = 588
WORDS_PER_FRAME = SAMPLES_PER_FRAME * 2 WORDS_PER_FRAME = SAMPLES_PER_FRAME * 2
BYTES_PER_FRAME = SAMPLES_PER_FRAME * 4 BYTES_PER_FRAME = SAMPLES_PER_FRAME * 4
@@ -334,3 +338,28 @@ def getRealPath(refPath, filePath):
return cpath return cpath
raise KeyError("Cannot find file for %r" % filePath) 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))

View File

@@ -600,7 +600,7 @@ class Program(log.Loggable):
self.debug('write .cue file to %s', cuePath) self.debug('write .cue file to %s', cuePath)
handle = open(cuePath, 'w') handle = open(cuePath, 'w')
# FIXME: do we always want utf-8 ? # 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() handle.close()
self.cuePath = cuePath self.cuePath = cuePath

View File

@@ -503,15 +503,19 @@ class Table(object, log.Loggable):
discId1[-1], discId1[-2], discId1[-3], discId1[-1], discId1[-2], discId1[-3],
self.getAudioTracks(), discId1, discId2, self.getCDDBDiscId()) 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. Dump our internal representation to a .cue file content.
""" """
lines = [] lines = []
def writeFile(path): def writeFile(path):
lines.append('FILE "%s" WAVE' % os.path.basename(path)) targetPath = common.getRelativePath(path, cuePath)
lines.append('FILE "%s" WAVE' % targetPath)
# header # header
main = ['PERFORMER', 'TITLE'] main = ['PERFORMER', 'TITLE']

View File

@@ -58,6 +58,13 @@ filling in the variables and expanding the file extension. Variables are:
- %A: album artist - %A: album artist
- %S: album sort name - %S: album sort name
- %d: disc title - %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): def addOptions(self):
@@ -69,7 +76,9 @@ filling in the variables and expanding the file extension. Variables are:
default=default) default=default)
self.parser.add_option('-O', '--output-directory', self.parser.add_option('-O', '--output-directory',
action="store", dest="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 # FIXME: have a cache of these pickles somewhere
self.parser.add_option('-T', '--toc-pickle', self.parser.add_option('-T', '--toc-pickle',
action="store", dest="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.track_template = options.track_template.decode('utf-8')
options.disc_template = options.disc_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): def do(self, args):
prog = program.Program(record=self.getRootCommand().record) prog = program.Program(record=self.getRootCommand().record)
runner = task.SyncRunner() 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 # FIXME: turn this into a method
def ripIfNotRipped(number): def ripIfNotRipped(number):
self.debug('ripIfNotRipped for track %d' % number)
# we can have a previous result # we can have a previous result
trackResult = prog.result.getTrackResult(number) trackResult = prog.result.getTrackResult(number)
if not trackResult: if not trackResult:
trackResult = result.TrackResult() trackResult = result.TrackResult()
prog.result.tracks.append(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, path = prog.getPath(prog.outdir, self.options.track_template,
mbdiscid, number) + '.' + profile.extension mbdiscid, number) + '.' + profile.extension
self.debug('ripIfNotRipped: path %r' % path)
trackResult.number = number trackResult.number = number
assert type(path) is unicode, "%r is not unicode" % path 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 # FIXME: optionally allow overriding reripping
if os.path.exists(path): 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' % ( self.stdout.write('Verifying track %d of %d: %s\n' % (
number, len(itable.tracks), number, len(itable.tracks),
os.path.basename(path).encode('utf-8'))) 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') handle.write(u'#EXTM3U\n')
def writeFile(handle, path, length): 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')) handle.write(u.encode('utf-8'))
u = '%s\n' % os.path.basename(path) u = '%s\n' % targetPath
handle.write(u.encode('utf-8')) handle.write(u.encode('utf-8'))

View File

@@ -25,3 +25,14 @@ class FramesTestCase(tcommon.TestCase):
class FormatTimeTestCase(tcommon.TestCase): class FormatTimeTestCase(tcommon.TestCase):
def testFormatTime(self): def testFormatTime(self):
self.assertEquals(common.formatTime(7202), '02:00:02.000') 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')

View File

@@ -14,8 +14,9 @@ from morituri.test import common
class CureTestCase(common.TestCase): class CureTestCase(common.TestCase):
def setUp(self): def setUp(self):
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__), self.path = os.path.join(os.path.dirname(__file__),
u'cure.toc')) u'cure.toc')
self.toc = toc.TocFile(self.path)
self.toc.parse() self.toc.parse()
self.assertEquals(len(self.toc.table.tracks), 13) self.assertEquals(len(self.toc.table.tracks), 13)
@@ -85,7 +86,7 @@ class CureTestCase(common.TestCase):
self.toc.table.absolutize() self.toc.table.absolutize()
cue = self.toc.table.cue() cue = self.toc.table.cue()
ref = open(os.path.join(os.path.dirname(__file__), 'cure.cue')).read() 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 # we verify it because it has failed in readdisc in the past
self.assertEquals(self.toc.table.getAccurateRipURL(), self.assertEquals(self.toc.table.getAccurateRipURL(),
@@ -109,8 +110,9 @@ class CureTestCase(common.TestCase):
class BlocTestCase(common.TestCase): class BlocTestCase(common.TestCase):
def setUp(self): def setUp(self):
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__), self.path = os.path.join(os.path.dirname(__file__),
u'bloc.toc')) u'bloc.toc')
self.toc = toc.TocFile(self.path)
self.toc.parse() self.toc.parse()
self.assertEquals(len(self.toc.table.tracks), 13) self.assertEquals(len(self.toc.table.tracks), 13)
@@ -160,8 +162,9 @@ class BlocTestCase(common.TestCase):
class BreedersTestCase(common.TestCase): class BreedersTestCase(common.TestCase):
def setUp(self): def setUp(self):
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__), self.path = os.path.join(os.path.dirname(__file__),
u'breeders.toc')) u'breeders.toc')
self.toc = toc.TocFile(self.path)
self.toc.parse() self.toc.parse()
self.assertEquals(len(self.toc.table.tracks), 13) self.assertEquals(len(self.toc.table.tracks), 13)
@@ -189,8 +192,9 @@ class BreedersTestCase(common.TestCase):
class LadyhawkeTestCase(common.TestCase): class LadyhawkeTestCase(common.TestCase):
def setUp(self): def setUp(self):
self.toc = toc.TocFile(os.path.join(os.path.dirname(__file__), self.path = os.path.join(os.path.dirname(__file__),
u'ladyhawke.toc')) u'ladyhawke.toc')
self.toc = toc.TocFile(self.path)
self.toc.parse() self.toc.parse()
self.assertEquals(len(self.toc.table.tracks), 13) self.assertEquals(len(self.toc.table.tracks), 13)
#import code; code.interact(local=locals()) #import code; code.interact(local=locals())