Update copyright years for 2013
[gpodder.git] / src / gpodder / gtkui / services.py
blob4da581ad1155d5532f9e25a29d8209f78a914ed0
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2013 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 # gpodder.gtkui.services - UI parts for the services module (2009-08-24)
26 import gpodder
27 _ = gpodder.gettext
29 from gpodder.services import ObservableService
31 import logging
32 logger = logging.getLogger(__name__)
34 from gpodder import util
35 from gpodder import coverart
37 import gtk
40 class CoverDownloader(ObservableService):
41 """
42 This class manages downloading cover art and notification
43 of other parts of the system. Downloading cover art can
44 happen either synchronously via get_cover() or in
45 asynchronous mode via request_cover(). When in async mode,
46 the cover downloader will send the cover via the
47 'cover-available' message (via the ObservableService).
48 """
50 def __init__(self):
51 self.downloader = coverart.CoverDownloader()
52 signal_names = ['cover-available', 'cover-removed']
53 ObservableService.__init__(self, signal_names)
55 def request_cover(self, channel, custom_url=None, avoid_downloading=False):
56 """
57 Sends an asynchronous request to download a
58 cover for the specific channel.
60 After the cover has been downloaded, the
61 "cover-available" signal will be sent with
62 the channel url and new cover as pixbuf.
64 If you specify a custom_url, the cover will
65 be downloaded from the specified URL and not
66 taken from the channel metadata.
68 The optional parameter "avoid_downloading",
69 when true, will make sure we return only
70 already-downloaded covers and return None
71 when we have no cover on the local disk.
72 """
73 logger.debug('cover download request for %s', channel.url)
74 util.run_in_background(lambda: self.__get_cover(channel,
75 custom_url, True, avoid_downloading))
77 def get_cover(self, channel, custom_url=None, avoid_downloading=False):
78 """
79 Sends a synchronous request to download a
80 cover for the specified channel.
82 The cover will be returned to the caller.
84 The custom_url has the same semantics as
85 in request_cover().
87 The optional parameter "avoid_downloading",
88 when true, will make sure we return only
89 already-downloaded covers and return None
90 when we have no cover on the local disk.
91 """
92 (url, pixbuf) = self.__get_cover(channel, custom_url, False, avoid_downloading)
93 return pixbuf
95 def replace_cover(self, channel, custom_url=None):
96 """
97 This is a convenience function that deletes
98 the current cover file and requests a new
99 cover from the URL specified.
101 self.request_cover(channel, custom_url)
103 def __get_cover(self, channel, url, async=False, avoid_downloading=False):
104 def get_filename():
105 return self.downloader.get_cover(channel.cover_file,
106 url or channel.cover_url, channel.url, channel.title,
107 channel.auth_username, channel.auth_password,
108 not avoid_downloading)
110 if url is not None:
111 filename = get_filename()
112 if filename.startswith(channel.cover_file):
113 logger.info('Replacing cover: %s', filename)
114 util.delete_file(filename)
116 filename = get_filename()
117 pixbuf = None
119 try:
120 pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
121 except Exception, e:
122 logger.warn('Cannot load cover art', exc_info=True)
123 if filename.startswith(channel.cover_file):
124 logger.info('Deleting broken cover: %s', filename)
125 util.delete_file(filename)
126 filename = get_filename()
127 pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
129 if async:
130 self.notify('cover-available', channel, pixbuf)
131 else:
132 return (channel.url, pixbuf)