Removed examples and gtk related files
This commit is contained in:
@@ -31,7 +31,6 @@ PYCHECKER_WHITELIST = \
|
||||
morituri/*/*.py
|
||||
|
||||
PYCHECKER_BLACKLIST = \
|
||||
morituri/common/taskgtk.py \
|
||||
morituri/extern/asyncsub.py \
|
||||
morituri/extern/log/log.py
|
||||
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import optparse
|
||||
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
|
||||
from morituri.image import image
|
||||
from morituri.common import task, checksum
|
||||
from morituri.program import cdrdao, cdparanoia
|
||||
|
||||
"""
|
||||
Find read offset by ripping a track from an AccurateRip CD.
|
||||
"""
|
||||
|
||||
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)
|
||||
|
||||
table.getTrackLength
|
||||
t = cdparanoia.ReadTrackTask(path, table, table.getTrackStart(track),
|
||||
table.getTrackEnd(track), 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)
|
||||
|
||||
# see http://www.accuraterip.com/driveoffsets.htm
|
||||
default = "0, 6, 12, 48, 91, 97, 102, 108, 120, " + \
|
||||
"564, 594, 667, 685, 691, 704, 738, 1194, 1292, 1336, 1776, -582"
|
||||
parser.add_option('-o', '--offsets',
|
||||
action="store", dest="offsets",
|
||||
help="list of offsets, comma-separated, "
|
||||
"colon-separated for ranges (defaults to %s)" %
|
||||
default,
|
||||
default=default)
|
||||
|
||||
options, args = parser.parse_args(argv[1:])
|
||||
|
||||
offsets = []
|
||||
blocks = options.offsets.split(',')
|
||||
for b in blocks:
|
||||
if ':' in b:
|
||||
a, b = b.split(':')
|
||||
offsets.extend(range(int(a), int(b) + 1))
|
||||
else:
|
||||
offsets.append(int(b))
|
||||
|
||||
# first get the Table Of Contents of the CD
|
||||
t = cdrdao.ReadTOCTask()
|
||||
|
||||
if options.runner == 'cli':
|
||||
runner = task.SyncRunner()
|
||||
function = climain
|
||||
elif options.runner == 'gtk':
|
||||
from morituri.common import taskgtk
|
||||
runner = taskgtk.GtkProgressRunner()
|
||||
function = gtkmain
|
||||
|
||||
function(runner, t)
|
||||
table = t.table
|
||||
|
||||
print "CDDB disc id", table.getCDDBDiscId()
|
||||
url = table.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'
|
||||
sys.exit(1)
|
||||
else:
|
||||
raise
|
||||
|
||||
if responses:
|
||||
print '%d AccurateRip responses found' % len(responses)
|
||||
|
||||
if responses[0].cddbDiscId != table.getCDDBDiscId():
|
||||
print "AccurateRip response discid different: %s" % \
|
||||
responses[0].cddbDiscId
|
||||
|
||||
# now rip the first track at various offsets, calculating AccurateRip
|
||||
# CRC, and matching it against the retrieved ones
|
||||
|
||||
def match(archecksum, track, responses):
|
||||
for i, r in enumerate(responses):
|
||||
if archecksum == r.checksums[track - 1]:
|
||||
return archecksum, i
|
||||
|
||||
return None, None
|
||||
|
||||
for offset in offsets:
|
||||
archecksum = arcs(runner, function, table, 1, offset)
|
||||
|
||||
print 'AR checksum calculated: %s' % archecksum
|
||||
|
||||
c, i = match(archecksum, 1, responses)
|
||||
if c:
|
||||
count = 1
|
||||
print 'MATCHED against response %d' % i
|
||||
print 'offset of device is likely', offset
|
||||
# now try and rip all other tracks as well
|
||||
for track in range(2, len(table.tracks) + 1):
|
||||
archecksum = arcs(runner, function, table, track, offset)
|
||||
c, i = match(archecksum, track, responses)
|
||||
if c:
|
||||
print 'MATCHED track %d against response %d' % (track, i)
|
||||
count += 1
|
||||
|
||||
if count == len(table.tracks):
|
||||
print 'OFFSET of device is', offset
|
||||
return
|
||||
else:
|
||||
print 'not all tracks matched, continuing'
|
||||
|
||||
print 'no matching offset found.'
|
||||
|
||||
|
||||
|
||||
|
||||
main(sys.argv)
|
||||
@@ -1,150 +0,0 @@
|
||||
# -*- Mode: Python -*-
|
||||
# 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/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import optparse
|
||||
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
import gtk
|
||||
|
||||
from morituri.image import image
|
||||
from morituri.common import task, taskgtk, checksum, log, accurip
|
||||
|
||||
def gtkmain(runner, taskk):
|
||||
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 main(argv):
|
||||
log.init()
|
||||
|
||||
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)
|
||||
|
||||
options, args = parser.parse_args(argv[1:])
|
||||
|
||||
path = 'test.cue'
|
||||
|
||||
try:
|
||||
path = sys.argv[1]
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
cueImage = image.Image(path)
|
||||
verifytask = image.ImageVerifyTask(cueImage)
|
||||
cuetask = image.AccurateRipChecksumTask(cueImage)
|
||||
|
||||
if options.runner == 'cli':
|
||||
runner = task.SyncRunner()
|
||||
function = climain
|
||||
elif options.runner == 'gtk':
|
||||
runner = taskgtk.GtkProgressRunner()
|
||||
function = gtkmain
|
||||
|
||||
cueImage.setup(runner)
|
||||
print
|
||||
print "CDDB disc id", cueImage.table.getCDDBDiscId()
|
||||
url = cueImage.table.getAccurateRipURL()
|
||||
print "AccurateRip URL", url
|
||||
|
||||
# FIXME: download url as a task too
|
||||
responses = []
|
||||
import urllib2
|
||||
try:
|
||||
handle = urllib2.urlopen(url)
|
||||
data = handle.read()
|
||||
responses = accurip.getAccurateRipResponses(data)
|
||||
except urllib2.HTTPError, e:
|
||||
if e.code == 404:
|
||||
print 'Album not found in AccurateRip database'
|
||||
else:
|
||||
raise
|
||||
|
||||
if responses:
|
||||
print '%d AccurateRip responses found' % len(responses)
|
||||
|
||||
if responses[0].cddbDiscId != cueImage.table.getCDDBDiscId():
|
||||
print "AccurateRip response discid different: %s" % \
|
||||
responses[0].cddbDiscId
|
||||
|
||||
function(runner, verifytask)
|
||||
function(runner, cuetask)
|
||||
|
||||
response = None # track which response matches, for all tracks
|
||||
|
||||
# loop over tracks
|
||||
for i, checksum in enumerate(cuetask.checksums):
|
||||
status = 'rip NOT accurate'
|
||||
|
||||
confidence = None
|
||||
archecksum = None
|
||||
|
||||
# match against each response's checksum
|
||||
for j, r in enumerate(responses):
|
||||
if "%08x" % checksum == r.checksums[i]:
|
||||
if not response:
|
||||
response = r
|
||||
else:
|
||||
assert r == response, \
|
||||
"checksum %s for %d matches wrong response %d, "\
|
||||
"checksum %s" % (
|
||||
checksum, i + 1, j + 1, response.checksums[i])
|
||||
status = 'rip accurate '
|
||||
archecksum = checksum
|
||||
confidence = response.confidences[i]
|
||||
|
||||
c = "(not found)"
|
||||
ar = "(not in database)"
|
||||
if responses:
|
||||
if not response:
|
||||
print 'ERROR: none of the responses matched.'
|
||||
else:
|
||||
maxConfidence = max(r.confidences[i] for r in responses)
|
||||
|
||||
c = "(confidence %3d)" % maxConfidence
|
||||
if confidence is not None:
|
||||
if confidence < maxConfidence:
|
||||
c = "(confidence %3d of %3d)" % (confidence, maxConfidence)
|
||||
|
||||
ar = ", AR [%s]" % response.checksums[i]
|
||||
print "Track %2d: %s %s [%08x]%s" % (
|
||||
i + 1, status, c, checksum, ar)
|
||||
|
||||
|
||||
main(sys.argv)
|
||||
@@ -1,98 +0,0 @@
|
||||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import optparse
|
||||
import tempfile
|
||||
import pickle
|
||||
import shutil
|
||||
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
|
||||
import gst
|
||||
|
||||
import gtk
|
||||
|
||||
|
||||
from morituri.common import task, taskgtk, common, encode
|
||||
|
||||
def gtkmain(runner, taskk):
|
||||
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)
|
||||
|
||||
class Listener(object):
|
||||
def __init__(self, persister):
|
||||
self._persister = persister
|
||||
|
||||
def progressed(self, task, value):
|
||||
pass
|
||||
|
||||
def described(self, task, description):
|
||||
pass
|
||||
|
||||
def started(self, task):
|
||||
pass
|
||||
|
||||
def stopped(self, task):
|
||||
self._persister.object[task.path] = task.trm
|
||||
print task.path, task.trm
|
||||
self._persister.persist()
|
||||
|
||||
|
||||
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)
|
||||
|
||||
options, args = parser.parse_args(argv[1:])
|
||||
|
||||
taglist = gst.TagList()
|
||||
taglist[gst.TAG_ARTIST] = 'Thomas'
|
||||
taglist[gst.TAG_TITLE] = 'Yes'
|
||||
taskk = encode.EncodeTask(args[0], args[1], taglist=taglist)
|
||||
|
||||
if options.runner == 'cli':
|
||||
runner = task.SyncRunner()
|
||||
function = climain
|
||||
elif options.runner == 'gtk':
|
||||
runner = taskgtk.GtkProgressRunner()
|
||||
function = gtkmain
|
||||
|
||||
function(runner, taskk)
|
||||
|
||||
main(sys.argv)
|
||||
@@ -1,58 +0,0 @@
|
||||
# -*- Mode: Python -*-
|
||||
# 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/>.
|
||||
|
||||
import sys
|
||||
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
|
||||
import gtk
|
||||
|
||||
from morituri.common import task, checksum, taskgtk
|
||||
|
||||
def main(path, start, end):
|
||||
progress = taskgtk.GtkProgressRunner()
|
||||
progress.connect('stop', lambda _: gtk.main_quit())
|
||||
|
||||
window = gtk.Window()
|
||||
window.add(progress)
|
||||
window.show_all()
|
||||
|
||||
checksumtask = checksum.CRC32Task(path, start, end)
|
||||
progress.run(checksumtask)
|
||||
|
||||
gtk.main()
|
||||
|
||||
print "CRC: %08X" % checksumtask.checksum
|
||||
|
||||
path = 'test.flac'
|
||||
|
||||
start = 0
|
||||
end = -1
|
||||
try:
|
||||
path = unicode(sys.argv[1])
|
||||
start = int(sys.argv[2])
|
||||
end = int(sys.argv[3])
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
main(path, start, end)
|
||||
@@ -1,48 +0,0 @@
|
||||
# -*- Mode: Python -*-
|
||||
# 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/>.
|
||||
|
||||
# EAC by default saves .cue files one directory up from the rip directories,
|
||||
# and only uses the title for the file name.
|
||||
# Move the .cue file into the corresponding directory, and rename it
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from morituri.image import cue
|
||||
|
||||
def move(path):
|
||||
print 'reading', path
|
||||
cuefile = cue.CueFile(path)
|
||||
cuefile.parse()
|
||||
|
||||
track = cuefile.tracks[0]
|
||||
idx, file = track.getIndex(1)
|
||||
destdir = os.path.dirname(cuefile.getRealPath(file.path))
|
||||
|
||||
if os.path.exists(destdir):
|
||||
dirname = os.path.basename(destdir)
|
||||
destination = os.path.join(destdir, dirname + '.cue')
|
||||
print 'moving %s to %s' % (path, destination)
|
||||
os.rename(path, destination)
|
||||
|
||||
for path in sys.argv[1:]:
|
||||
move(path)
|
||||
@@ -1,40 +0,0 @@
|
||||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
|
||||
from morituri.image import cue
|
||||
|
||||
def main(path):
|
||||
cuefile = cue.CueFile(path)
|
||||
cuefile.parse()
|
||||
|
||||
print cuefile.tracks
|
||||
|
||||
path = 'test.cue'
|
||||
|
||||
try:
|
||||
path = sys.argv[1]
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
main(path)
|
||||
@@ -1,415 +0,0 @@
|
||||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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()
|
||||
window.remove(runner)
|
||||
window.hide()
|
||||
|
||||
def climain(runner, taskk):
|
||||
runner.run(taskk)
|
||||
|
||||
class TrackMetadata(object):
|
||||
artist = None
|
||||
title = None
|
||||
|
||||
class DiscMetadata(object):
|
||||
artist = None
|
||||
title = None
|
||||
various = False
|
||||
tracks = None
|
||||
|
||||
def __init__(self):
|
||||
self.tracks = []
|
||||
|
||||
def filterForPath(text):
|
||||
return "-".join(text.split("/"))
|
||||
|
||||
def musicbrainz(discid):
|
||||
metadata = DiscMetadata()
|
||||
|
||||
import musicbrainz2.disc as mbdisc
|
||||
import musicbrainz2.webservice as mbws
|
||||
|
||||
|
||||
# Setup a Query object.
|
||||
service = mbws.WebService()
|
||||
query = mbws.Query(service)
|
||||
|
||||
|
||||
# Query for all discs matching the given DiscID.
|
||||
try:
|
||||
filter = mbws.ReleaseFilter(discId=discid)
|
||||
results = query.getReleases(filter)
|
||||
except mbws.WebServiceError, e:
|
||||
print "Error:", e
|
||||
return
|
||||
|
||||
|
||||
# No disc matching this DiscID has been found.
|
||||
if len(results) == 0:
|
||||
print "Disc is not yet in the MusicBrainz database."
|
||||
print "Consider adding it."
|
||||
return
|
||||
|
||||
|
||||
# Display the returned results to the user.
|
||||
print 'Matching releases:'
|
||||
|
||||
for result in results:
|
||||
release = result.release
|
||||
print 'Artist :', release.artist.name
|
||||
print 'Title :', release.title
|
||||
print
|
||||
|
||||
|
||||
# Select one of the returned releases. We just pick the first one.
|
||||
selectedRelease = results[0].release
|
||||
|
||||
|
||||
# The returned release object only contains title and artist, but no tracks.
|
||||
# Query the web service once again to get all data we need.
|
||||
try:
|
||||
inc = mbws.ReleaseIncludes(artist=True, tracks=True, releaseEvents=True)
|
||||
release = query.getReleaseById(selectedRelease.getId(), inc)
|
||||
except mbws.WebServiceError, e:
|
||||
print "Error:", e
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
isSingleArtist = release.isSingleArtistRelease()
|
||||
metadata.various = not isSingleArtist
|
||||
metadata.title = release.title
|
||||
metadata.artist = release.artist.getUniqueName()
|
||||
|
||||
print "%s - %s" % (release.artist.getUniqueName(), release.title)
|
||||
|
||||
i = 1
|
||||
for t in release.tracks:
|
||||
track = TrackMetadata()
|
||||
if isSingleArtist:
|
||||
track.artist = metadata.artist
|
||||
track.title = t.title
|
||||
else:
|
||||
track.artist = t.artist.name
|
||||
track.title = t.title
|
||||
metadata.tracks.append(track)
|
||||
|
||||
return metadata
|
||||
|
||||
def getPath(template, metadata, i):
|
||||
# returns without extension
|
||||
|
||||
v = {}
|
||||
|
||||
v['t'] = '%02d' % (i + 1)
|
||||
|
||||
# default values
|
||||
v['A'] = 'Unknown Artist'
|
||||
v['d'] = 'Unknown Disc'
|
||||
|
||||
v['a'] = v['A']
|
||||
v['n'] = 'Unknown Track'
|
||||
|
||||
if metadata:
|
||||
v['A'] = filterForPath(metadata.artist)
|
||||
v['d'] = filterForPath(metadata.title)
|
||||
if i >= 0:
|
||||
v['a'] = filterForPath(metadata.tracks[i].artist)
|
||||
v['n'] = filterForPath(metadata.tracks[i].title)
|
||||
else:
|
||||
# htoa defaults to disc's artist
|
||||
v['a'] = filterForPath(metadata.artist)
|
||||
v['n'] = filterForPath('Hidden Track One Audio')
|
||||
|
||||
import re
|
||||
template = re.sub(r'%(\w)', r'%(\1)s', template)
|
||||
|
||||
return template % v
|
||||
|
||||
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)
|
||||
default = '%A - %d/%t. %a - %n'
|
||||
parser.add_option('', '--track-template',
|
||||
action="store", dest="track_template",
|
||||
help="template for track file naming (default %s)" % default,
|
||||
default=default)
|
||||
default = '%A - %d/%A - %d'
|
||||
parser.add_option('', '--disc-template',
|
||||
action="store", dest="disc_template",
|
||||
help="template for disc file naming (default %s)" % default,
|
||||
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, which is fast
|
||||
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
|
||||
assert ittoc.hasTOC()
|
||||
|
||||
# already show us some info based on this
|
||||
print "CDDB disc id", ittoc.getCDDBDiscId()
|
||||
metadata = musicbrainz(ittoc.getMusicBrainzDiscId())
|
||||
|
||||
# now, read the complete index table, which is slower
|
||||
ptable = common.Persister(options.table_pickle or None)
|
||||
if not ptable.object:
|
||||
t = cdrdao.ReadTableTask()
|
||||
function(runner, t)
|
||||
ptable.persist(t.table)
|
||||
itable = ptable.object
|
||||
|
||||
assert itable.hasTOC()
|
||||
|
||||
assert itable.getCDDBDiscId() == ittoc.getCDDBDiscId(), \
|
||||
"full table's id %s differs from toc id %s" % (
|
||||
itable.getCDDBDiscId(), ittoc.getCDDBDiscId())
|
||||
assert itable.getMusicBrainzDiscId() == ittoc.getMusicBrainzDiscId()
|
||||
|
||||
lastTrackStart = 0
|
||||
|
||||
# check for hidden track one audio
|
||||
htoapath = None
|
||||
index = None
|
||||
track = itable.tracks[0]
|
||||
try:
|
||||
index = track.getIndex(0)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if index:
|
||||
start = index.absolute
|
||||
stop = track.getIndex(1).absolute
|
||||
print 'Found Hidden Track One Audio from frame %d to %d' % (start, stop)
|
||||
|
||||
# rip it
|
||||
htoapath = getPath(options.track_template, metadata, -1) + '.wav'
|
||||
htoalength = stop - start
|
||||
if not os.path.exists(htoapath):
|
||||
print 'Ripping track %d: %s' % (0, os.path.basename(htoapath))
|
||||
t = cdparanoia.ReadVerifyTrackTask(htoapath, ittoc,
|
||||
start, stop - 1,
|
||||
offset=int(options.offset))
|
||||
function(runner, t)
|
||||
if t.checksum:
|
||||
print 'Checksums match for track %d' % 0
|
||||
else:
|
||||
print 'ERROR: checksums did not match for track %d' % 0
|
||||
# overlay this rip onto the Table
|
||||
itable.setFile(1, 0, htoapath, htoalength, 0)
|
||||
|
||||
|
||||
for i, track in enumerate(itable.tracks):
|
||||
path = getPath(options.track_template, metadata, i) + '.wav'
|
||||
dirname = os.path.dirname(path)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
|
||||
# FIXME: optionally allow overriding reripping
|
||||
if not os.path.exists(path):
|
||||
print 'Ripping track %d: %s' % (i + 1, os.path.basename(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)
|
||||
else:
|
||||
print 'ERROR: checksums did not match for track %d' % (i + 1)
|
||||
|
||||
# overlay this rip onto the Table
|
||||
itable.setFile(i + 1, 1, path, ittoc.getTrackLength(i + 1), i + 1)
|
||||
|
||||
|
||||
### write disc files
|
||||
discName = getPath(options.disc_template, metadata, i)
|
||||
dirname = os.path.dirname(discName)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
|
||||
# write .cue file
|
||||
cuePath = '%s.cue' % discName
|
||||
handle = open(cuePath, 'w')
|
||||
handle.write(itable.cue())
|
||||
handle.close()
|
||||
|
||||
# write .m3u file
|
||||
m3uPath = '%s.m3u' % discName
|
||||
handle = open(m3uPath, 'w')
|
||||
handle.write('#EXTM3U\n')
|
||||
if htoapath:
|
||||
handle.write('#EXTINF:%d,%s\n' % (
|
||||
htoalength / common.FRAMES_PER_SECOND,
|
||||
os.path.basename(htoapath[:-4])))
|
||||
handle.write('%s\n' % os.path.basename(htoapath))
|
||||
|
||||
for i, track in enumerate(itable.tracks):
|
||||
path = getPath(options.track_template, metadata, i) + '.wav'
|
||||
handle.write('#EXTINF:%d,%s\n' % (
|
||||
itable.getTrackLength(i + 1) / common.FRAMES_PER_SECOND,
|
||||
os.path.basename(path)))
|
||||
handle.write('%s\n' % os.path.basename(path))
|
||||
handle.close()
|
||||
|
||||
# verify using accuraterip
|
||||
print "CDDB disc id", itable.getCDDBDiscId()
|
||||
print "MusicBrainz disc id", itable.getMusicBrainzDiscId()
|
||||
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 responses found' % len(responses)
|
||||
|
||||
if responses[0].cddbDiscId != itable.getCDDBDiscId():
|
||||
print "AccurateRip response discid different: %s" % \
|
||||
responses[0].cddbDiscId
|
||||
|
||||
|
||||
# FIXME: put accuraterip verification into a separate task/function
|
||||
# and apply here
|
||||
cueImage = image.Image(cuePath)
|
||||
verifytask = image.ImageVerifyTask(cueImage)
|
||||
cuetask = image.AccurateRipChecksumTask(cueImage)
|
||||
function(runner, verifytask)
|
||||
function(runner, cuetask)
|
||||
|
||||
response = None # track which response matches, for all tracks
|
||||
|
||||
# loop over tracks
|
||||
for i, sum in enumerate(cuetask.checksums):
|
||||
status = 'rip NOT accurate'
|
||||
|
||||
confidence = None
|
||||
arsum = None
|
||||
|
||||
# match against each response's checksum
|
||||
for j, r in enumerate(responses):
|
||||
if "%08x" % sum == r.checksums[i]:
|
||||
if not response:
|
||||
response = r
|
||||
else:
|
||||
assert r == response, \
|
||||
"checksum %s for %d matches wrong response %d, "\
|
||||
"checksum %s" % (
|
||||
sum, i + 1, j + 1, response.checksums[i])
|
||||
status = 'rip accurate '
|
||||
arsum = sum
|
||||
confidence = response.confidences[i]
|
||||
|
||||
c = "(not found)"
|
||||
ar = "(not in database)"
|
||||
if responses:
|
||||
if not response:
|
||||
print 'ERROR: none of the responses matched.'
|
||||
else:
|
||||
maxConfidence = max(r.confidences[i] for r in responses)
|
||||
|
||||
c = "(max confidence %3d)" % maxConfidence
|
||||
if confidence is not None:
|
||||
if confidence < maxConfidence:
|
||||
c = "(confidence %3d of %3d)" % (confidence, maxConfidence)
|
||||
|
||||
ar = ", AR [%s]" % response.checksums[i]
|
||||
print "Track %2d: %s %s [%08x]%s" % (
|
||||
i + 1, status, c, sum, ar)
|
||||
|
||||
|
||||
|
||||
|
||||
main(sys.argv)
|
||||
@@ -1,73 +0,0 @@
|
||||
# -*- Mode: Python -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
import os
|
||||
import sys
|
||||
import optparse
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
from morituri.common import task, checksum, log
|
||||
from morituri.program import cdrdao, cdparanoia
|
||||
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
|
||||
def main():
|
||||
log.init()
|
||||
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
default = 0
|
||||
parser.add_option('-o', '--offset',
|
||||
action="store", dest="offset",
|
||||
help="sample offset (defaults to %d)" % default,
|
||||
default=default)
|
||||
|
||||
options, args = parser.parse_args(sys.argv[1:])
|
||||
|
||||
runner = task.SyncRunner()
|
||||
|
||||
# first do a simple TOC scan
|
||||
t = cdrdao.ReadTOCTask()
|
||||
runner.run(t)
|
||||
toc = t.table
|
||||
|
||||
offset = t.table.tracks[0].getIndex(1).absolute
|
||||
|
||||
if offset < 150:
|
||||
print 'Disc is unlikely to have Hidden Track One Audio.'
|
||||
else:
|
||||
print 'Disc seems to have a %d frame HTOA.' % offset
|
||||
|
||||
|
||||
# now do a more extensive scan
|
||||
t = cdrdao.ReadTableTask()
|
||||
runner.run(t)
|
||||
|
||||
# now check if we have a hidden track one audio
|
||||
track = t.table.tracks[0]
|
||||
try:
|
||||
index = track.getIndex(0)
|
||||
except KeyError:
|
||||
print 'No Hidden Track One Audio found.'
|
||||
return
|
||||
|
||||
start = index.absolute
|
||||
stop = track.getIndex(1).absolute
|
||||
print 'Found Hidden Track One Audio from frame %d to %d' % (start, stop)
|
||||
|
||||
# rip it
|
||||
riptask = cdparanoia.ReadVerifyTrackTask('track00.wav', t.table,
|
||||
start, stop - 1,
|
||||
offset=int(options.offset))
|
||||
runner.run(riptask)
|
||||
|
||||
print 'runner done'
|
||||
|
||||
if riptask.checksum is not None:
|
||||
print 'Checksums match'
|
||||
else:
|
||||
print 'Checksums did not match'
|
||||
|
||||
main()
|
||||
@@ -1,21 +0,0 @@
|
||||
# -*- Mode: Python -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
from morituri.common import task, log
|
||||
from morituri.program import cdrdao
|
||||
|
||||
def main():
|
||||
log.init()
|
||||
runner = task.SyncRunner()
|
||||
t = cdrdao.ReadTableTask()
|
||||
runner.run(t)
|
||||
print 'runner done', t.toc
|
||||
|
||||
if not t.table:
|
||||
print 'Failed to read TOC'
|
||||
return
|
||||
|
||||
for track in t.table.tracks:
|
||||
print track.getIndex(1).absolute
|
||||
|
||||
main()
|
||||
@@ -1,49 +0,0 @@
|
||||
# -*- Mode: Python -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import stat
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
from morituri.common import task, checksum, log
|
||||
from morituri.image import table
|
||||
from morituri.program import cdparanoia
|
||||
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
|
||||
def main():
|
||||
log.init()
|
||||
|
||||
|
||||
runner = task.SyncRunner()
|
||||
|
||||
checksums = []
|
||||
if len(sys.argv) > 1:
|
||||
path = sys.argv[1]
|
||||
else:
|
||||
fd, path = tempfile.mkstemp(suffix='.morituri.wav')
|
||||
os.close(fd)
|
||||
print 'storing track to %s' % path
|
||||
|
||||
fakeTable = table.Table([
|
||||
table.Track( 1, 0, 15536),
|
||||
])
|
||||
|
||||
t = cdparanoia.ReadVerifyTrackTask(path, fakeTable, 1000, 3000, offset=0)
|
||||
|
||||
|
||||
runner.run(t)
|
||||
|
||||
print 'runner done'
|
||||
|
||||
if t.checksum is not None:
|
||||
print 'Checksums match'
|
||||
else:
|
||||
print 'Checksums do not match'
|
||||
|
||||
|
||||
main()
|
||||
126
examples/trm.py
126
examples/trm.py
@@ -1,126 +0,0 @@
|
||||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import optparse
|
||||
import tempfile
|
||||
import pickle
|
||||
import shutil
|
||||
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
import gtk
|
||||
|
||||
from morituri.common import checksum, task, taskgtk, common
|
||||
|
||||
def gtkmain(runner, taskk):
|
||||
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)
|
||||
|
||||
class Listener(object):
|
||||
def __init__(self, persister):
|
||||
self._persister = persister
|
||||
|
||||
def progressed(self, task, value):
|
||||
pass
|
||||
|
||||
def described(self, task, description):
|
||||
pass
|
||||
|
||||
def started(self, task):
|
||||
pass
|
||||
|
||||
def stopped(self, task):
|
||||
self._persister.object[task.path] = task.trm
|
||||
print task.path, task.trm
|
||||
self._persister.persist()
|
||||
|
||||
|
||||
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)
|
||||
parser.add_option('-p', '--playlist',
|
||||
action="store", dest="playlist",
|
||||
help="playlist to analyze files from")
|
||||
parser.add_option('-P', '--pickle',
|
||||
action="store", dest="pickle",
|
||||
help="pickle to store trms to")
|
||||
|
||||
|
||||
options, args = parser.parse_args(argv[1:])
|
||||
|
||||
paths = []
|
||||
if len(args) > 0:
|
||||
paths.extend(args[0:])
|
||||
if options.playlist:
|
||||
paths.extend(open(options.playlist).readlines())
|
||||
|
||||
mtask = task.MultiCombinedTask()
|
||||
listener = None
|
||||
|
||||
ptrms = common.Persister(options.pickle or None, {})
|
||||
if options.pickle:
|
||||
listener = Listener(ptrms)
|
||||
print 'Using pickle %s' % options.pickle
|
||||
trms = ptrms.object
|
||||
|
||||
for path in paths:
|
||||
path = path.rstrip()
|
||||
if path in trms.keys():
|
||||
continue
|
||||
trmtask = checksum.TRMTask(path)
|
||||
if listener:
|
||||
trmtask.addListener(listener)
|
||||
mtask.addTask(trmtask)
|
||||
mtask.description = 'Fingerprinting files'
|
||||
|
||||
|
||||
if options.runner == 'cli':
|
||||
runner = task.SyncRunner()
|
||||
function = climain
|
||||
elif options.runner == 'gtk':
|
||||
runner = taskgtk.GtkProgressRunner()
|
||||
function = gtkmain
|
||||
|
||||
function(runner, mtask)
|
||||
|
||||
print
|
||||
for trmtask in mtask.tasks:
|
||||
print trmtask.trm
|
||||
|
||||
main(sys.argv)
|
||||
1
morituri/extern/Makefile.am
vendored
1
morituri/extern/Makefile.am
vendored
@@ -23,7 +23,6 @@ taskdir = $(PYTHONLIBDIR)/morituri/extern/task
|
||||
task_PYTHON = \
|
||||
task/__init__.py \
|
||||
task/task.py \
|
||||
task/taskgtk.py \
|
||||
task/gstreamer.py
|
||||
|
||||
EXTRA_DIST = python-command/scripts/help2man
|
||||
|
||||
73
morituri/extern/task/taskgtk.py
vendored
73
morituri/extern/task/taskgtk.py
vendored
@@ -1,73 +0,0 @@
|
||||
# -*- Mode: Python; test-case-name: test_taskgtk -*-
|
||||
# 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/>.
|
||||
|
||||
import gobject
|
||||
import gtk
|
||||
|
||||
import task
|
||||
|
||||
class GtkProgressRunner(gtk.VBox, task.TaskRunner):
|
||||
"""
|
||||
I am a widget that shows progress on a task.
|
||||
"""
|
||||
|
||||
__gsignals__ = {
|
||||
'stop': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ())
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
gtk.VBox.__init__(self)
|
||||
self.set_border_width(6)
|
||||
self.set_spacing(6)
|
||||
|
||||
self._label = gtk.Label()
|
||||
self.add(self._label)
|
||||
|
||||
self._progress = gtk.ProgressBar()
|
||||
self.add(self._progress)
|
||||
|
||||
def run(self, task):
|
||||
self._task = task
|
||||
self._label.set_text(task.description)
|
||||
task.addListener(self)
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
||||
task.start(self)
|
||||
|
||||
def schedule(self, delta, callable, *args, **kwargs):
|
||||
def c():
|
||||
callable(*args, **kwargs)
|
||||
return False
|
||||
gobject.timeout_add(int(delta * 1000L), c)
|
||||
|
||||
def started(self, task):
|
||||
pass
|
||||
|
||||
def stopped(self, task):
|
||||
self.emit('stop')
|
||||
# self._task.removeListener(self)
|
||||
|
||||
def progressed(self, task, value):
|
||||
self._progress.set_fraction(value)
|
||||
|
||||
def described(self, task, description):
|
||||
self._label.set_text(description)
|
||||
Reference in New Issue
Block a user