Index: ahttp.py ================================================================== --- ahttp.py +++ ahttp.py @@ -23,19 +23,20 @@ # Sets either text or percentage of main windows' status bar. # # Can either take a float parameter (e.g. 0.99 for % indicator) # or text message. Alternatively two parameters to update both. -def progress_feedback(*args): +def progress_feedback(*args, **kwargs): # use reset values if none given if not args: args = ["", 1.0] + timeout = kwargs.get("timeout", 50) # send to main win if feedback: - try: [feedback(d, timeout=50) for d in args] + try: [feedback(d, timeout=timeout) for d in args] except: pass # prepare default query object session = requests.Session() @@ -59,11 +60,11 @@ statusmsg=None, timeout=9.25, quieter=0 ): # statusbar info if not quieter: - progress_feedback(url) + progress_feedback(url, timeout=timeout/1.5) # combine headers headers = {} if ajax: headers["X-Requested-With"] = "XMLHttpRequest" Index: channels/favicon.py ================================================================== --- channels/favicon.py +++ channels/favicon.py @@ -7,11 +7,11 @@ # { name: favicon_delete_stub , type: bool, value: 1, description: "Don't accept any placeholder favicons." } # [ main-name: google_homepage ] # [ main-name: load_favicon ] # type: feature # category: ui -# version: 1.8 +# version: 1.9 # depends: streamtuner2 >= 2.1.9, python:pil # priority: standard # # This module fetches a favicon for each station, or a small banner # or logo for some channel modules. It converts .ico image files and @@ -47,20 +47,18 @@ # Has recently been rewritten, is somewhat less entangled with other # modules now: # # · GenericChannel presets row["favicon"] with cache image filenames -# in any case. It uses row["homepage"] or row["img"] as template. -# -# · The url-to-filename shortening functionality in GenChan.prepare() -# is identical to that in row_to_fn() here. +# in any case. It calls row_to_fn() per prepare_filters hook after +# station list updates. # # · uikit.columns() merely checks row["favicon"] for file existence # when redrawing a station list. # -# · main only calls .update_playing() via hooks["play"], and the menu -# invokes .update_all() +# · main calls .update_playing() on hooks["play"], +# or .update_all() per menu command # # · urllib is no longer required. Using just ahttp/requests API now. # # · Might need unhtml() utility from channels/__init__ later.. # @@ -102,25 +100,28 @@ #kwargs[pixstore] = self.parent.channel()._ls, ... self.parent.thread(self.update_rows, *args, **kwargs) # Main callback for a single play() event - def update_playing(self, row, pixstore=None): + def update_playing(self, row, pixstore=None, channel=None, **x): # Homepage search if conf.google_homepage and not len(row.get("homepage", "")): - google_find_homepage(row) + found = google_find_homepage(row) + # could call channel.save() now to preserve found homepage URL + else: + found = False # Favicon only for currently playing station if conf.load_favicon: if row.get("homepage") or row.get("img"): - self.update_all([row], pixstore=pixstore) + self.update_all([row], pixstore=pixstore, always_update=found) # Run through rows[] to update "favicon" from "homepage" or "img", # optionally display new image right away in ListStore - def update_rows(self, entries, pixstore=None): + def update_rows(self, entries, pixstore=None, always_update=False): for i,row in enumerate(entries): ok = False # Try just once if row.get("homepage") in tried_urls: @@ -131,20 +132,25 @@ # Cache image filename: have or can't have favicon_fn = row_to_fn(row) if not favicon_fn: continue - if os.path.exists(favicon_fn): - continue try: - # Custom "img" banner/logo as favicon - if row.get("img"): + # Image already exists + if os.path.exists(favicon_fn): + if not always_update: + continue + else: # For freshly added ["homepage"] when favicon already + ok = True # exists in cache. Then just update pix store. + + # Download custom "img" banner/logo as favicon + elif row.get("img"): tried_urls.append(row["img"]) ok = banner_localcopy(row["img"], favicon_fn) - # Homepage to favicon + # Fetch homepage favicon into local png elif row.get("homepage"): tried_urls.append(row["homepage"]) if conf.favicon_google_first: ok = fav_google_ico2png(row["homepage"], favicon_fn) else: @@ -186,13 +192,16 @@ ls[i][pix_entry] = p except Exception as e: log.ERR("Update_pixstore image", fn, "error:", e) - # Run after any channel .update_streams() to populate "favicon" + # Run after any channel .update_streams() to populate row["favicon"] + # from `homepage` or `img` url. def prepare_filter_favicon(self, row): row["favicon"] = row_to_fn(row) + + #--- somewhat unrelated --- # # Should become a distinct feature plugin. - It just depends on correct @@ -212,16 +221,17 @@ # Use literal station title now title = row["title"] #title = title.group(0).replace(" ", "%20") # Do 'le google search - html = ahttp.get("http://www.google.com/search", params=dict(hl="en", q=title, client="streamtuner2"), ajax=1) + html = ahttp.get("http://www.google.com/search", params=dict(hl="en", q=title, client="streamtuner2"), ajax=1, timeout=3.5) # Find first URL hit url = rx_u.findall(html) if url: row["homepage"] = ahttp.fix_url(url[0]) + return True pass #----------------- @@ -233,11 +243,11 @@ url = row.get("img") or row.get("homepage") or None if url: url = url.lower() url = rx_strip_proto.sub("", url) # strip proto:// and trailing / url = rx_non_wordchr.sub("_", url) # remove any non-word characters - url = "{}/{}.png".format(conf.icon_dir, url) + url = "{}/{}.png".format(conf.icon_dir, url) # prefix cache directory return url # Copy banner row["img"] into icons/ directory @@ -252,11 +262,11 @@ if imgdata: return store_image(imgdata, fn) -# Check valid image, possibly convert, and save to cache filename +# Check for valid image binary, possibly convert or resize, then save to cache filename def store_image(imgdata, fn, resize=None): # Convert accepted formats -- even PNG for filtering now if re.match(br'^(.PNG|GIF\d+|.{0,15}JFIF|\x00\x00\x01\x00|.{0,255}]+svg)', imgdata): try: @@ -330,12 +340,12 @@ # Download HTML, look for favicon name in . # -# Very rough, doesn't respect any and manually patches -# icon path to homepage url; nor does any entity decoding. +# Very rough: doesn't respect any and manually patches +# icon path to homepage url; doesn't do much HTML entity decoding. # def html_link_icon(url, href="/favicon.png"): html = ahttp.get(url, encoding="iso-8859-1", timeout=4.5, quieter=1) # Extract for link in re.findall(r""" ]+) > """, html, re.X): Index: st2.py ================================================================== --- st2.py +++ st2.py @@ -274,11 +274,11 @@ self.status("Starting player...") channel = self.channel() pixstore = [channel.ls, channel.pix_entry, channel.rowno()] row = channel.play() self.status("") - [callback(row, pixstore=pixstore) for callback in self.hooks["play"]] + [callback(row, pixstore=pixstore, channel=channel) for callback in self.hooks["play"]] # Recording: invoke streamripper for current stream URL def on_record_clicked(self, widget): self.status("Recording station...") row = self.channel().record()