1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2018 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)
28 from gi
.repository
import GdkPixbuf
31 from gpodder
import coverart
, util
32 from gpodder
.services
import ObservableService
36 logger
= logging
.getLogger(__name__
)
39 class CoverDownloader(ObservableService
):
41 This class manages downloading cover art and notification
42 of other parts of the system. Downloading cover art can
43 happen either synchronously via get_cover() or in
44 asynchronous mode via request_cover(). When in async mode,
45 the cover downloader will send the cover via the
46 'cover-available' message (via the ObservableService).
50 self
.downloader
= coverart
.CoverDownloader()
51 signal_names
= ['cover-available', 'cover-removed']
52 ObservableService
.__init
__(self
, signal_names
)
54 def request_cover(self
, channel
, custom_url
=None, avoid_downloading
=False):
56 Sends an asynchronous request to download a
57 cover for the specific channel.
59 After the cover has been downloaded, the
60 "cover-available" signal will be sent with
61 the channel url and new cover as pixbuf.
63 If you specify a custom_url, the cover will
64 be downloaded from the specified URL and not
65 taken from the channel metadata.
67 The optional parameter "avoid_downloading",
68 when true, will make sure we return only
69 already-downloaded covers and return None
70 when we have no cover on the local disk.
72 logger
.debug('cover download request for %s', channel
.url
)
73 util
.run_in_background(lambda: self
.__get
_cover
(channel
,
74 custom_url
, True, avoid_downloading
))
76 def get_cover(self
, channel
, custom_url
=None, avoid_downloading
=False):
78 Sends a synchronous request to download a
79 cover for the specified channel.
81 The cover will be returned to the caller.
83 The custom_url has the same semantics as
86 The optional parameter "avoid_downloading",
87 when true, will make sure we return only
88 already-downloaded covers and return None
89 when we have no cover on the local disk.
91 (url
, pixbuf
) = self
.__get
_cover
(channel
, custom_url
, False, avoid_downloading
)
94 def replace_cover(self
, channel
, custom_url
=None):
96 This is a convenience function that deletes
97 the current cover file and requests a new
98 cover from the URL specified.
100 self
.request_cover(channel
, custom_url
)
102 def __get_cover(self
, channel
, url
, async_mode
=False, avoid_downloading
=False):
104 return self
.downloader
.get_cover(channel
.cover_file
,
105 url
or channel
.cover_url
, channel
.url
, channel
.title
,
106 channel
.auth_username
, channel
.auth_password
,
107 not avoid_downloading
)
110 filename
= get_filename()
111 if filename
.startswith(channel
.cover_file
):
112 logger
.info('Replacing cover: %s', filename
)
113 util
.delete_file(filename
)
115 filename
= get_filename()
119 pixbuf
= GdkPixbuf
.Pixbuf
.new_from_file(filename
)
120 except Exception as e
:
121 logger
.warning('Cannot load cover art', exc_info
=True)
122 if pixbuf
is None and filename
.startswith(channel
.cover_file
):
123 logger
.info('Deleting broken cover: %s', filename
)
124 util
.delete_file(filename
)
125 filename
= get_filename()
127 pixbuf
= GdkPixbuf
.Pixbuf
.new_from_file(filename
)
128 except Exception as e
:
129 logger
.warning('Corrupt cover art on server, deleting', exc_info
=True)
130 util
.delete_file(filename
)
133 self
.notify('cover-available', channel
, pixbuf
)
135 return (channel
.url
, pixbuf
)