diff --git a/ChangeLog b/ChangeLog index b69d5b0..babd4e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-05-04 Thomas Vander Stichele + + * examples/readdisc.py (added): + Add an example to read a whole disc. Doesn't work yet. + 2009-05-04 Thomas Vander Stichele * examples/readhtoa.py: diff --git a/examples/readdisc.py b/examples/readdisc.py new file mode 100644 index 0000000..e14781b --- /dev/null +++ b/examples/readdisc.py @@ -0,0 +1,203 @@ +# -*- Mode: Python; test-case-name: morituri.test.test_header -*- +# 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 . + +import os +import sys +import tempfile +import optparse +import pickle +import shutil + +import gobject +gobject.threads_init() + +from morituri.common import common, task, checksum +from morituri.image import image, cue, table +from morituri.program import cdrdao, cdparanoia + +""" +Rip a disc. +""" + +from morituri.common import log +log.init() + +def gtkmain(runner, taskk): + import gtk + runner.connect('stop', lambda _: gtk.main_quit()) + + window = gtk.Window() + window.add(runner) + window.show_all() + + runner.run(taskk) + + gtk.main() + +def climain(runner, taskk): + runner.run(taskk) + + +def arcs(runner, function, table, track, offset): + # rips the track with the given offset, return the arcs checksum + print 'ripping track %r with offset %d' % (track, offset) + + fd, path = tempfile.mkstemp(suffix='.track%02d.offset%d.morituri.wav' % ( + track, offset)) + os.close(fd) + + track = table.tracks[track - 1] + t = cdparanoia.ReadTrackTask(path, table, track.start, track.end, offset) + t.description = 'Ripping with offset %d' % offset + function(runner, t) + + t = checksum.AccurateRipChecksumTask(path, trackNumber=track, + trackCount=len(table.tracks)) + function(runner, t) + + # os.unlink(path) + return "%08x" % t.checksum + +def main(argv): + parser = optparse.OptionParser() + + default = 'cli' + parser.add_option('-r', '--runner', + action="store", dest="runner", + help="runner ('cli' or 'gtk', defaults to %s)" % default, + default=default) + default = 0 + parser.add_option('-o', '--offset', + action="store", dest="offset", + help="sample offset (defaults to %d)" % default, + default=default) + parser.add_option('-t', '--table-pickle', + action="store", dest="table_pickle", + help="pickle to use for reading and writing the table", + default=default) + parser.add_option('-T', '--toc-pickle', + action="store", dest="toc_pickle", + help="pickle to use for reading and writing the TOC", + default=default) + + options, args = parser.parse_args(argv[1:]) + + if options.runner == 'cli': + runner = task.SyncRunner() + function = climain + elif options.runner == 'gtk': + from morituri.common import taskgtk + runner = taskgtk.GtkProgressRunner() + function = gtkmain + + # first, read the normal TOC and full index table + ptoc = common.Persister(options.toc_pickle or None) + if not ptoc.object: + t = cdrdao.ReadTOCTask() + function(runner, t) + ptoc.persist(t.table) + ittoc = ptoc.object + + ptable = common.Persister(options.table_pickle or None) + if not ptable.object: + t = cdrdao.ReadIndexTableTask() + function(runner, t) + ptable.persist(t.toc) + itable = ptable.object + import code; code.interact(local=locals()) + + lastTrackStart = 0 + + for i, track in enumerate(itable.tracks): + print 'Ripping track %d' % (i + 1) + path = 'track%02d.wav' % (i + 1) + # FIXME: optionally allow overriding reripping + if not os.path.exists(path): + t = cdparanoia.ReadVerifyTrackTask(path, ittoc, ittoc.getTrackStart(i + 1), + ittoc.getTrackEnd(i + 1), + offset=int(options.offset)) + t.description = 'Reading Track %d' % (i + 1) + function(runner, t) + if t.checksum: + print 'Checksums match for track %d' % (i + 1) + + ittrack = table.ITTrack(i + 1) + # we know the .toc file represents a single wav rip, so all offsets + # are absolute since beginning of disc + + # copy over indexes, adjusting the offset + tocTrack = itable.tracks[i] + + # first copy over index 0 if there is any + try: + sector, _ = tocTrack.getIndex(0) + t.index(0, path=path, relative=sector - lastTrackStart) + except KeyError: + pass + lastTrackStart, _ = tocTrack.getIndex(1) + + indexes = itable.tracks[i]._indexes + numbers = indexes.keys() + numbers.sort() + if 0 in numbers: + del numbers[0] + for number in numbers: + sector, _ = tocTrack.getIndex(number) + ittrack.index(number, path=path, relative=sector - lastTrackStart) + #itable.tracks.append(ittrack) + + + + # FIXME: this is the part where our IndexTable reader should convert + # a .toc file to a IndexTable we can dump .cue from + print ittoc.cue() + + # verify using accuraterip + print "CDDB disc id", itable.getCDDBDiscId() + url = itable.getAccurateRipURL() + print "AccurateRip URL", url + + # FIXME: download url as a task too + responses = [] + import urllib2 + try: + handle = urllib2.urlopen(url) + data = handle.read() + responses = image.getAccurateRipResponses(data) + except urllib2.HTTPError, e: + if e.code == 404: + print 'Album not found in AccurateRip database' + else: + raise + + if responses: + print '%d AccurateRip reponses found' % len(responses) + + if responses[0].cddbDiscId != itable.getCDDBDiscId(): + print "AccurateRip response discid different: %s" % \ + responses[0].cddbDiscId + + + + + +main(sys.argv)