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)
29 from gpodder
.services
import ObservableService
32 logger
= logging
.getLogger(__name__
)
34 from gpodder
import util
35 from gpodder
import coverart
40 class CoverDownloader(ObservableService
):
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).
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):
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.
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):
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
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.
92 (url
, pixbuf
) = self
.__get
_cover
(channel
, custom_url
, False, avoid_downloading
)
95 def replace_cover(self
, channel
, custom_url
=None):
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):
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
)
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()
120 pixbuf
= gtk
.gdk
.pixbuf_new_from_file(filename
)
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
)
130 self
.notify('cover-available', channel
, pixbuf
)
132 return (channel
.url
, pixbuf
)