Adding magazine covers
authorEd Page <eopage@byu.net>
Sun, 16 May 2010 04:04:36 +0000 (23:04 -0500)
committerEd Page <eopage@byu.net>
Sun, 16 May 2010 04:05:06 +0000 (23:05 -0500)
src/imagestore.py
src/mormonchannel_gtk.py
src/stream_index.py
src/windows/magazines.py

index 7bd0e96..0cb4813 100644 (file)
@@ -1,8 +1,18 @@
+from __future__ import with_statement
+
 import os
 import os
+import logging
 
 import cairo
 import gtk
 
 
 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):
 
 
 class ImageStore(object):
 
@@ -49,6 +59,15 @@ class ImageStore(object):
                self._storePath = storePath
                self._cachePath = cachePath
 
                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)
        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)
 
                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_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
index 40727ab..7c570cd 100755 (executable)
@@ -3,7 +3,6 @@
 
 """
 @bug Fix segfault on closing of window while playing
 
 """
 @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
 @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._index = stream_index.AudioIndex()
                self._player = player.Player(self._index)
 
+               self._store.start()
                self._index.start()
                try:
                        if not hildonize.IS_HILDON_SUPPORTED:
                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._load_settings()
                except:
                        self._index.stop()
+                       self._store.stop()
                        raise
 
        def _save_settings(self):
                        raise
 
        def _save_settings(self):
@@ -112,6 +113,7 @@ class MormonChannelProgram(hildonize.get_app_class()):
                        self._save_settings()
 
                        self._index.stop()
                        self._save_settings()
 
                        self._index.stop()
+                       self._store.stop()
 
                        try:
                                self._deviceState.close()
 
                        try:
                                self._deviceState.close()
index d638e71..6f45842 100644 (file)
@@ -33,7 +33,6 @@ class Connection(object):
                if kwds is None:
                        kwds = {}
 
                if kwds is None:
                        kwds = {}
 
-               self._indexing.clear_tasks()
                self._indexing.add_task(
                        getattr(self._backend, func),
                        args,
                self._indexing.add_task(
                        getattr(self._backend, func),
                        args,
index 97c1f36..11c96d5 100644 (file)
@@ -52,14 +52,38 @@ class MagazinesWindow(windows._base.ListWindow):
                        return
 
                self._hide_loading()
                        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)
 
                        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()
 
                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()
        @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)
 
                        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)
                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))
 
                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)
        def _window_from_node(self, node):
                issuesWindow = MagazineArticlesWindow(self._player, self._store, node)
                issuesWindow.window.set_modal(True)