From bf983084fcb46a045684cb62014a0693527907e3 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Sat, 15 May 2010 23:04:36 -0500 Subject: [PATCH 1/1] Adding magazine covers --- src/imagestore.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++ src/mormonchannel_gtk.py | 4 ++- src/stream_index.py | 1 - src/windows/magazines.py | 47 +++++++++++++++++++++++++++++++++- 4 files changed, 113 insertions(+), 3 deletions(-) diff --git a/src/imagestore.py b/src/imagestore.py index 7bd0e96..0cb4813 100644 --- a/src/imagestore.py +++ b/src/imagestore.py @@ -1,8 +1,18 @@ +from __future__ import with_statement + import os +import logging import cairo import gtk +import browser_emu +from util import go_utils +import util.misc as misc_utils + + +_moduleLogger = logging.getLogger(__name__) + class ImageStore(object): @@ -49,6 +59,15 @@ class ImageStore(object): self._storePath = storePath self._cachePath = cachePath + self._browser = browser_emu.MozillaEmulator() + self._downloader = go_utils.AsyncPool() + + def start(self): + self._downloader.start() + + def stop(self): + self._downloader.stop() + def get_surface_from_store(self, imageName): path = os.path.join(self._storePath, imageName) image = cairo.ImageSurface.create_from_png(path) @@ -69,6 +88,51 @@ class ImageStore(object): path = os.path.join(self._storePath, imageName) return gtk.gdk.pixbuf_new_from_file(path) + def get_pixbuf_from_url(self, url, on_success, on_error): + # @ todo Test bad image for both paths + filepath = self._url_to_cache(url) + if os.path.exists(filepath): + pix = gtk.gdk.pixbuf_new_from_file(filepath) + try: + on_success(pix) + except Exception: + pass + doDownload = False + else: + doDownload = True + + if doDownload: + self._get_image( + url, + lambda filepath: on_success(gtk.gdk.pixbuf_new_from_file(filepath)), + on_error, + ) + def get_pixbuf_animation_from_store(self, imageName): path = os.path.join(self._storePath, imageName) return gtk.gdk.PixbufAnimation(path) + + def _get_image(self, url, on_success, on_error): + self._downloader.add_task( + self._browser.download, + (url, ), + {}, + lambda image: self._on_get_image(url, image, on_success, on_error), + on_error, + ) + + @misc_utils.log_exception(_moduleLogger) + def _on_get_image(self, url, image, on_success, on_error): + try: + filepath = self._url_to_cache(url) + _moduleLogger.info("Saved %s" % filepath) + with open(filepath, "wb") as f: + f.write(image) + on_success(filepath) + except Exception, e: + on_error(e) + + def _url_to_cache(self, url): + filename = url.rsplit("/", 1)[-1] + filepath = os.path.join(self._cachePath, filename) + return filepath diff --git a/src/mormonchannel_gtk.py b/src/mormonchannel_gtk.py index 40727ab..7c570cd 100755 --- a/src/mormonchannel_gtk.py +++ b/src/mormonchannel_gtk.py @@ -3,7 +3,6 @@ """ @bug Fix segfault on closing of window while playing -@todo Add images for Magazines and Issues @todo Need to confirm id's are persistent (not just for todos but broken behavior on transition) @todo Track recent @todo Persisted Pause @@ -54,6 +53,7 @@ class MormonChannelProgram(hildonize.get_app_class()): self._index = stream_index.AudioIndex() self._player = player.Player(self._index) + self._store.start() self._index.start() try: if not hildonize.IS_HILDON_SUPPORTED: @@ -74,6 +74,7 @@ class MormonChannelProgram(hildonize.get_app_class()): self._load_settings() except: self._index.stop() + self._store.stop() raise def _save_settings(self): @@ -112,6 +113,7 @@ class MormonChannelProgram(hildonize.get_app_class()): self._save_settings() self._index.stop() + self._store.stop() try: self._deviceState.close() diff --git a/src/stream_index.py b/src/stream_index.py index d638e71..6f45842 100644 --- a/src/stream_index.py +++ b/src/stream_index.py @@ -33,7 +33,6 @@ class Connection(object): if kwds is None: kwds = {} - self._indexing.clear_tasks() self._indexing.add_task( getattr(self._backend, func), args, diff --git a/src/windows/magazines.py b/src/windows/magazines.py index 97c1f36..11c96d5 100644 --- a/src/windows/magazines.py +++ b/src/windows/magazines.py @@ -52,14 +52,38 @@ class MagazinesWindow(windows._base.ListWindow): return self._hide_loading() - for programNode in programs: + for i, programNode in enumerate(programs): program = programNode.get_properties() img = self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["nomagazineimage"]) row = programNode, img, program["title"] self._model.append(row) + programNode.get_children(self._create_on_issues(i), self._on_error) + self._select_row() + def _create_on_issues(self, row): + return lambda issues: self._on_issues(row, issues) + + @misc_utils.log_exception(_moduleLogger) + def _on_issues(self, row, issues): + for issue in issues: + self._store.get_pixbuf_from_url( + issue.get_properties()["pictureURL"], + lambda pix: self._on_image(row, pix), + self._on_error, + ) + break + else: + _moduleLogger.info("No issues for magazine %s" % row) + + @misc_utils.log_exception(_moduleLogger) + def _on_image(self, row, pix): + treeiter = self._model.iter_nth_child(None, row) + self._model.set_value(treeiter, 1, pix) + treeiter = self._model.iter_nth_child(None, row) + self._model.row_changed((row, ), treeiter) + @misc_utils.log_exception(_moduleLogger) def _on_error(self, exception): self._hide_loading() @@ -128,6 +152,12 @@ class MagazineIssuesWindow(windows._base.ListWindow): row = programNode, img, program["title"] self._model.append(row) + self._store.get_pixbuf_from_url( + program["pictureURL"], + self._create_on_image(programNode), + self._on_error, + ) + self._select_row() @misc_utils.log_exception(_moduleLogger) @@ -135,6 +165,21 @@ class MagazineIssuesWindow(windows._base.ListWindow): self._hide_loading() self._errorBanner.push_message(str(exception)) + def _create_on_image(self, programNode): + return lambda pix: self._on_image(programNode, pix) + + @misc_utils.log_exception(_moduleLogger) + def _on_image(self, childNode, pix): + for i, row in enumerate(self._model): + if row[0] is childNode: + break + else: + raise RuntimeError("Could not find %r" % childNode) + treeiter = self._model.iter_nth_child(None, i) + self._model.set_value(treeiter, 1, pix) + treeiter = self._model.iter_nth_child(None, i) + self._model.row_changed((i, ), treeiter) + def _window_from_node(self, node): issuesWindow = MagazineArticlesWindow(self._player, self._store, node) issuesWindow.window.set_modal(True) -- 1.7.9.5