* morituri/result/result.py:
Change toctable to table since it's a full index table. * morituri/common/Makefile.am: * morituri/common/program.py (added): Add module and class for program state. * morituri/rip/cd.py: Use the program state to clean up the do() function.
This commit is contained in:
10
ChangeLog
10
ChangeLog
@@ -1,3 +1,13 @@
|
|||||||
|
2009-06-07 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
|
* morituri/result/result.py:
|
||||||
|
Change toctable to table since it's a full index table.
|
||||||
|
* morituri/common/Makefile.am:
|
||||||
|
* morituri/common/program.py (added):
|
||||||
|
Add module and class for program state.
|
||||||
|
* morituri/rip/cd.py:
|
||||||
|
Use the program state to clean up the do() function.
|
||||||
|
|
||||||
2009-06-07 Thomas Vander Stichele <thomas at apestaart dot org>
|
2009-06-07 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
* morituri/rip/cd.py:
|
* morituri/rip/cd.py:
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ morituri_PYTHON = \
|
|||||||
drive.py \
|
drive.py \
|
||||||
log.py \
|
log.py \
|
||||||
logcommand.py \
|
logcommand.py \
|
||||||
|
program.py \
|
||||||
renamer.py \
|
renamer.py \
|
||||||
task.py \
|
task.py \
|
||||||
taskgtk.py
|
taskgtk.py
|
||||||
|
|||||||
103
morituri/common/program.py
Normal file
103
morituri/common/program.py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
# -*- Mode: Python; test-case-name: morituri.test.test_common_program -*-
|
||||||
|
# vi:si:et:sw=4:sts=4:ts=4
|
||||||
|
|
||||||
|
# Morituri - for those about to RIP
|
||||||
|
|
||||||
|
# Copyright (C) 2009 Thomas Vander Stichele
|
||||||
|
|
||||||
|
# This file is part of morituri.
|
||||||
|
#
|
||||||
|
# morituri is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# morituri 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with morituri. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Common functionality and class for all programs using morituri.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from morituri.common import common
|
||||||
|
from morituri.result import result
|
||||||
|
from morituri.program import cdrdao
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class Program(object):
|
||||||
|
"""
|
||||||
|
I maintain program state and functionality.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cuePath = None
|
||||||
|
logPath = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.result = result.RipResult()
|
||||||
|
|
||||||
|
def _getTableCachePath(self):
|
||||||
|
path = os.path.join(os.path.expanduser('~'), '.morituri', 'cache',
|
||||||
|
'table')
|
||||||
|
return path
|
||||||
|
|
||||||
|
def unmountDevice(self, device):
|
||||||
|
"""
|
||||||
|
Unmount the given device if it is mounted, as happens with automounted
|
||||||
|
data tracks.
|
||||||
|
"""
|
||||||
|
proc = open('/proc/mounts').read()
|
||||||
|
if device in proc:
|
||||||
|
print 'Device %s is mounted, unmounting' % device
|
||||||
|
os.system('umount %s' % device)
|
||||||
|
|
||||||
|
def getTable(self, runner, cddbdiscid, device):
|
||||||
|
"""
|
||||||
|
Retrieve the Table either from the cache or the drive.
|
||||||
|
|
||||||
|
@rtype: L{table.Table}
|
||||||
|
"""
|
||||||
|
path = self._getTableCachePath()
|
||||||
|
|
||||||
|
pcache = common.PersistedCache(path)
|
||||||
|
ptable = pcache.get(cddbdiscid)
|
||||||
|
|
||||||
|
if not ptable.object:
|
||||||
|
t = cdrdao.ReadTableTask(device=device)
|
||||||
|
runner.run(t)
|
||||||
|
ptable.persist(t.table)
|
||||||
|
itable = ptable.object
|
||||||
|
assert itable.hasTOC()
|
||||||
|
|
||||||
|
self.result.table = itable
|
||||||
|
|
||||||
|
return itable
|
||||||
|
|
||||||
|
def writeCue(self, discName):
|
||||||
|
assert self.result.table.canCue()
|
||||||
|
|
||||||
|
cuePath = '%s.cue' % discName
|
||||||
|
handle = open(cuePath, 'w')
|
||||||
|
# FIXME: do we always want utf-8 ?
|
||||||
|
handle.write(self.result.table.cue().encode('utf-8'))
|
||||||
|
handle.close()
|
||||||
|
|
||||||
|
self.cuePath = cuePath
|
||||||
|
|
||||||
|
return cuePath
|
||||||
|
|
||||||
|
def writeLog(self, discName, logger):
|
||||||
|
logPath = '%s.log' % discName
|
||||||
|
handle = open(logPath, 'w')
|
||||||
|
handle.write(logger.log(res).encode('utf-8'))
|
||||||
|
handle.close()
|
||||||
|
|
||||||
|
self.logPath = logPath
|
||||||
|
|
||||||
|
return logPath
|
||||||
@@ -50,10 +50,12 @@ class RipResult:
|
|||||||
I can be used to write log files.
|
I can be used to write log files.
|
||||||
|
|
||||||
@ivar offset: sample read offset
|
@ivar offset: sample read offset
|
||||||
|
@ivar table: the full index table
|
||||||
|
@type table: L{morituri.common.table.Table}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
offset = 0
|
offset = 0
|
||||||
toctable = None
|
table = None
|
||||||
artist = None
|
artist = None
|
||||||
title = None
|
title = None
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ gobject.threads_init()
|
|||||||
import gst
|
import gst
|
||||||
|
|
||||||
from morituri.common import logcommand, task, checksum, common, accurip, log
|
from morituri.common import logcommand, task, checksum, common, accurip, log
|
||||||
from morituri.common import drive, encode
|
from morituri.common import drive, encode, program
|
||||||
from morituri.result import result
|
from morituri.result import result
|
||||||
from morituri.image import image, cue, table
|
from morituri.image import image, cue, table
|
||||||
from morituri.program import cdrdao, cdparanoia
|
from morituri.program import cdrdao, cdparanoia
|
||||||
@@ -261,10 +261,6 @@ class Rip(logcommand.LogCommand):
|
|||||||
action="store", dest="output_directory",
|
action="store", dest="output_directory",
|
||||||
help="output directory (defaults to current directory)")
|
help="output directory (defaults to current directory)")
|
||||||
# FIXME: have a cache of these pickles somewhere
|
# FIXME: have a cache of these pickles somewhere
|
||||||
self.parser.add_option('-t', '--table-pickle',
|
|
||||||
action="store", dest="table_pickle",
|
|
||||||
help="pickle to use for reading and writing the table",
|
|
||||||
default=default)
|
|
||||||
self.parser.add_option('-T', '--toc-pickle',
|
self.parser.add_option('-T', '--toc-pickle',
|
||||||
action="store", dest="toc_pickle",
|
action="store", dest="toc_pickle",
|
||||||
help="pickle to use for reading and writing the TOC",
|
help="pickle to use for reading and writing the TOC",
|
||||||
@@ -289,7 +285,9 @@ class Rip(logcommand.LogCommand):
|
|||||||
|
|
||||||
|
|
||||||
def do(self, args):
|
def do(self, args):
|
||||||
|
prog = program.Program()
|
||||||
runner = task.SyncRunner()
|
runner = task.SyncRunner()
|
||||||
|
|
||||||
def function(r, t):
|
def function(r, t):
|
||||||
r.run(t)
|
r.run(t)
|
||||||
|
|
||||||
@@ -297,10 +295,7 @@ class Rip(logcommand.LogCommand):
|
|||||||
device = self.parentCommand.options.device
|
device = self.parentCommand.options.device
|
||||||
print 'Checking device', device
|
print 'Checking device', device
|
||||||
|
|
||||||
proc = open('/proc/mounts').read()
|
prog.unmountDevice(device)
|
||||||
if device in proc:
|
|
||||||
print 'Device %s is mounted, unmounting' % device
|
|
||||||
os.system('umount %s' % device)
|
|
||||||
|
|
||||||
# first, read the normal TOC, which is fast
|
# first, read the normal TOC, which is fast
|
||||||
ptoc = common.Persister(self.options.toc_pickle or None)
|
ptoc = common.Persister(self.options.toc_pickle or None)
|
||||||
@@ -322,17 +317,7 @@ class Rip(logcommand.LogCommand):
|
|||||||
print ittoc.getMusicBrainzSubmitURL()
|
print ittoc.getMusicBrainzSubmitURL()
|
||||||
|
|
||||||
# now, read the complete index table, which is slower
|
# now, read the complete index table, which is slower
|
||||||
path = os.path.join(os.path.expanduser('~'), '.morituri', 'cache',
|
itable = prog.getTable(runner, ittoc.getCDDBDiscId(), device)
|
||||||
'table')
|
|
||||||
pcache = common.PersistedCache(path)
|
|
||||||
ptable = pcache.get(ittoc.getCDDBDiscId())
|
|
||||||
if not ptable.object:
|
|
||||||
t = cdrdao.ReadTableTask(device=self.parentCommand.options.device)
|
|
||||||
function(runner, t)
|
|
||||||
ptable.persist(t.table)
|
|
||||||
itable = ptable.object
|
|
||||||
|
|
||||||
assert itable.hasTOC()
|
|
||||||
|
|
||||||
assert itable.getCDDBDiscId() == ittoc.getCDDBDiscId(), \
|
assert itable.getCDDBDiscId() == ittoc.getCDDBDiscId(), \
|
||||||
"full table's id %s differs from toc id %s" % (
|
"full table's id %s differs from toc id %s" % (
|
||||||
@@ -349,9 +334,8 @@ class Rip(logcommand.LogCommand):
|
|||||||
extension = profile.extension
|
extension = profile.extension
|
||||||
|
|
||||||
# result
|
# result
|
||||||
res = result.RipResult()
|
res = prog.result
|
||||||
res.offset = int(self.options.offset)
|
res.offset = int(self.options.offset)
|
||||||
res.toctable = itable
|
|
||||||
res.artist = metadata and metadata.artist or 'Unknown Artist'
|
res.artist = metadata and metadata.artist or 'Unknown Artist'
|
||||||
res.title = metadata and metadata.title or 'Unknown Title'
|
res.title = metadata and metadata.title or 'Unknown Title'
|
||||||
# cdio is optional for now
|
# cdio is optional for now
|
||||||
@@ -462,18 +446,12 @@ class Rip(logcommand.LogCommand):
|
|||||||
|
|
||||||
### write disc files
|
### write disc files
|
||||||
discName = getPath(outdir, self.options.disc_template, metadata,
|
discName = getPath(outdir, self.options.disc_template, metadata,
|
||||||
mbdiscid, i)
|
mbdiscid, 0)
|
||||||
dirname = os.path.dirname(discName)
|
dirname = os.path.dirname(discName)
|
||||||
if not os.path.exists(dirname):
|
if not os.path.exists(dirname):
|
||||||
os.makedirs(dirname)
|
os.makedirs(dirname)
|
||||||
|
|
||||||
# write .cue file
|
prog.writeCue(discName)
|
||||||
assert itable.canCue()
|
|
||||||
cuePath = '%s.cue' % discName
|
|
||||||
handle = open(cuePath, 'w')
|
|
||||||
# FIXME: do we always want utf-8 ?
|
|
||||||
handle.write(itable.cue().encode('utf-8'))
|
|
||||||
handle.close()
|
|
||||||
|
|
||||||
# write .m3u file
|
# write .m3u file
|
||||||
m3uPath = '%s.m3u' % discName
|
m3uPath = '%s.m3u' % discName
|
||||||
@@ -519,7 +497,7 @@ class Rip(logcommand.LogCommand):
|
|||||||
|
|
||||||
# FIXME: put accuraterip verification into a separate task/function
|
# FIXME: put accuraterip verification into a separate task/function
|
||||||
# and apply here
|
# and apply here
|
||||||
cueImage = image.Image(cuePath)
|
cueImage = image.Image(prog.cuePath)
|
||||||
verifytask = image.ImageVerifyTask(cueImage)
|
verifytask = image.ImageVerifyTask(cueImage)
|
||||||
cuetask = image.AccurateRipChecksumTask(cueImage)
|
cuetask = image.AccurateRipChecksumTask(cueImage)
|
||||||
function(runner, verifytask)
|
function(runner, verifytask)
|
||||||
@@ -573,13 +551,9 @@ class Rip(logcommand.LogCommand):
|
|||||||
i + 1, status, c, csum, ar)
|
i + 1, status, c, csum, ar)
|
||||||
|
|
||||||
# write log file
|
# write log file
|
||||||
discName = getPath(outdir, self.options.disc_template, metadata,
|
|
||||||
mbdiscid, i)
|
|
||||||
logPath = '%s.log' % discName
|
|
||||||
logger = result.getLogger()
|
logger = result.getLogger()
|
||||||
handle = open(logPath, 'w')
|
prog.writeLog(discName, logger)
|
||||||
handle.write(logger.log(res).encode('utf-8'))
|
|
||||||
handle.close()
|
|
||||||
|
|
||||||
class CD(logcommand.LogCommand):
|
class CD(logcommand.LogCommand):
|
||||||
summary = "handle CD's"
|
summary = "handle CD's"
|
||||||
|
|||||||
Reference in New Issue
Block a user