From 8486ee782b4568d4437cb455f57dd4da10cf6b61 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Sat, 11 Apr 2009 14:46:19 +0000 Subject: [PATCH] * examples/ARcue.py: * examples/gtkcrc.py: * morituri/common/task.py: Make a real Task interface and use it. Make runners reusable for multiple tasks. gtkcrc.py seems to be blocking updates however. --- ChangeLog | 9 ++++++ examples/ARcue.py | 4 +-- examples/gtkcrc.py | 54 +++++++++++++++++++++++++------- morituri/common/task.py | 69 +++++++++++++++++++++++++++++++---------- 4 files changed, 107 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5fe03c6..dbcb4df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-04-11 Thomas Vander Stichele + + * examples/ARcue.py: + * examples/gtkcrc.py: + * morituri/common/task.py: + Make a real Task interface and use it. + Make runners reusable for multiple tasks. + gtkcrc.py seems to be blocking updates however. + 2009-04-11 Thomas Vander Stichele * morituri/test (added): diff --git a/examples/ARcue.py b/examples/ARcue.py index a71a2dc..f944e1d 100644 --- a/examples/ARcue.py +++ b/examples/ARcue.py @@ -58,8 +58,8 @@ def main(path): print 'ERROR: path %s not found' % file.path continue - runner = task.SyncRunner(crctask) - runner.run() + runner = task.SyncRunner() + runner.run(crctask) print "%08x" % crctask.crc diff --git a/examples/gtkcrc.py b/examples/gtkcrc.py index e5d9e14..24dfc97 100644 --- a/examples/gtkcrc.py +++ b/examples/gtkcrc.py @@ -1,4 +1,4 @@ -# -*- Mode: Python; test-case-name: morituri.test.test_header -*- +# -*- Mode: Python -*- # vi:si:et:sw=4:sts=4:ts=4 # Morituri - for those about to RIP @@ -32,32 +32,46 @@ import gtk from morituri.common import task -class TaskProgress(gtk.VBox): +class TaskProgress(gtk.VBox, task.TaskRunner): __gsignals__ = { 'stop': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()) } - def __init__(self, task): + def __init__(self): + gst.info('__init__') gtk.VBox.__init__(self) self.set_border_width(6) self.set_spacing(6) - label = gtk.Label(task.description) - self.add(label) + 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() - def start(self): + def started(self): pass - def stop(self): + def stopped(self): self.emit('stop') + # self._task.removeListener(self) - def progress(self, value): + def progressed(self, value): + gst.info('progressed') + # FIXME: why is this not painting the progress bar ? + print 'progress', value self._progress.set_fraction(value) + while gtk.events_pending(): + gtk.main_iteration() + path = 'test.flac' @@ -78,15 +92,33 @@ try: except: pass -crctask = task.CRCTask(path, start, end) +crctask = task.CRC32Task(path, start, end) + +class DummTask(task.Task): + def start(self): + task.Task.start(self) + gobject.timeout_add(1000L, self._wind) + + def _wind(self): + self.setProgress(min(self.progress + 0.1, 1.0)) + + if self.progress >= 1.0: + self.stop() + return + + gobject.timeout_add(1000L, self._wind) + +#crctask = DummyTask() window = gtk.Window() -progress = TaskProgress(crctask) +progress = TaskProgress() progress.connect('stop', lambda _: gtk.main_quit()) window.add(progress) window.show_all() -crctask.start() +progress.run(crctask) + +print 'going main' gtk.main() diff --git a/morituri/common/task.py b/morituri/common/task.py index 571de87..182f23c 100644 --- a/morituri/common/task.py +++ b/morituri/common/task.py @@ -32,6 +32,12 @@ FRAMES_PER_DISC_FRAME = 588 SAMPLES_PER_DISC_FRAME = FRAMES_PER_DISC_FRAME * 4 class Task(object): + """ + I wrap a task in an asynchronous interface. + I can be listened to for starting, stopping, and progress updates. + + @ivar description: what am I doing + """ description = 'I am doing something.' progress = 0.0 @@ -41,24 +47,24 @@ class Task(object): _listeners = None def debug(self, *args, **kwargs): - return + #return print args, kwargs sys.stdout.flush() pass def start(self): self.running = True - self._notifyListeners('start') + self._notifyListeners('started') def stop(self): self.debug('stopping') self.running = False - self._notifyListeners('stop') + self._notifyListeners('stopped') def setProgress(self, value): if value - self.progress > self.increment or value >= 1.0: self.progress = value - self._notifyListeners('progress', value) + self._notifyListeners('progressed', value) self.debug('notifying progress', value) def addListener(self, listener): @@ -171,7 +177,8 @@ class CRCTask(Task): frame = self._first + self._bytes / 4 framesDone = frame - self._frameStart progress = float(framesDone) / float((self._frameLength)) - self.setProgress(progress) + # marshall to the main thread + gobject.timeout_add(0L, self.setProgress, progress) def do_crc_buffer(self, buffer, crc): @@ -256,25 +263,55 @@ class CRCAudioRipTask(CRCTask): # offset / FRAMES_PER_DISC_FRAME, offset, value, crc) return crc -class SyncRunner: - def __init__(self, task): - self._task = task +class TaskRunner: + """ + I am a base class for task runners. + Task runners should be reusable. + """ - def run(self): + def run(self, task): + """ + Run the given task. + + @type task: Task + """ + raise NotImplementedError + + # listener callbacks + def progressed(self, value): + """ + Implement me to be informed about progress. + + @type value: float + @param value: progress, from 0.0 to 1.0 + """ + + def started(self): + """ + Implement me to be informed about the task starting. + """ + + def stopped(self): + """ + Implement me to be informed about the task starting. + """ + +class SyncRunner(TaskRunner): + def run(self, task): + self._task = task self._loop = gobject.MainLoop() self._task.addListener(self) self._task.start() self._loop.run() - def start(self): - pass - - def progress(self, value): - sys.stdout.write('Progress: %3d %%\r' % (value * 100.0)) + def progressed(self, value): + sys.stdout.write('%s %3d %%\r' % ( + self._task.description, value * 100.0)) sys.stdout.flush() if value >= 1.0: - print 'Progress: 100 %' + sys.stdout.write('%s %3d %%\n' % ( + self._task.description, 100.0)) - def stop(self): + def stopped(self): self._loop.quit()