Internet radio browser GUI for music/video streams from various directory services.

⌈⌋ ⎇ branch:  streamtuner2


Diff

Differences From Artifact [cef590a4be]:

  • File channels/favicon.py — part of check-in [8c7b4f2662] at 2015-05-14 18:41:05 on branch trunk — Remove a few options from configuration dialog; now available in [feature] plugin tabs for favicon module. Favicon module exposes google_station_homepage, and retrieval methods, but no longer `conf.show_favicons` (which is decided on just by having the plugin enabled - or not.) Introduce conf.auto_save_stations for favicon/DND plugin. (user: mario, size: 13285) [annotate] [blame] [check-ins using]

To Artifact [8987f1daae]:


1
2
3
4

5
6
7
8
9
10
11
1
2
3

4
5
6
7
8
9
10
11



-
+







# encoding: utf-8
# api: streamtuner2
# title: Favicons
# description: Display station favicons/logos. Instantly download them when â–¸playing.
# description: Load and display station favicons/logos.
# config:
#    { name: load_favicon, type: bool, value: 1, description: "Load favicon instantly when â–¸playing a station.", color: yellow }
#    { name: favicon_google_first, type: bool, value: 1, description: "Prefer faster Google favicon to PNG conversion service." }
#    { name: favicon_delete_stub , type: bool, value: 1, description: "Don't accept any placeholder favicons." }
#    { name: google_homepage, type: bool, value: 0, description: "Google missing station homepages right away." }
# type: feature
# category: ui
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87







-
+







    module = "favicon"
    meta = plugin_meta()
    
    
    # Register with main
    def __init__(self, parent):
    
        # Reference main, and register station .play() hook for conf.load_favicon
        # Reference main, and register station .play() hook
        self.parent, self.main = parent, parent
        parent.hooks["play"].append(self.update_playing)

        # Register in channel/streams updating pipeline (to predefine row["favicon"] filename from `homepage` or `img`)
        channels.GenericChannel.prepare_filters.append(self.prepare_filter_favicon)

        # Prepare favicon cache directory
108
109
110
111
112
113
114
115

116
117
118
119
120

121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139

140
141
142
143
144
145
146
108
109
110
111
112
113
114

115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147







-
+




-
+












+






-
+







                channel.save()
        else:
            found = False

        # Favicon only for currently playing station
        if conf.load_favicon:
            if row.get("homepage") or row.get("img"):
                self.parent.thread(self.update_rows, [row], pixstore=pixstore, always_update=found)
                self.parent.thread(self.update_rows, [row], pixstore=pixstore, fresh_homepage=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, always_update=False, **x):
    def update_rows(self, entries, pixstore=None, fresh_homepage=False, **x):
        for i,row in enumerate(entries):
            ok = False

            # Try just once
            if row.get("homepage") in tried_urls:
                continue
            # Ignore existing ["favicon"] filename
            if row.get("favicon") and False:
                pass

            # Cache image filename: have or can't have
            favicon_fn = row_to_fn(row)
            print favicon_fn
            if not favicon_fn:
                continue

            try:
                # Image already exists
                if os.path.exists(favicon_fn):
                    if not always_update:
                    if not fresh_homepage:
                        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"])
232
233
234
235
236
237
238

239

240
241
242

243
244
245
246
247









248
249
250
251
252
253
254
233
234
235
236
237
238
239
240
241
242
243
244

245
246




247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262







+

+


-
+

-
-
-
-
+
+
+
+
+
+
+
+
+







    pass
#-----------------




# Convert row["img"] or row["homepage"] into local favicon cache filename
# Use just domain for homepages, but most of the url for banner/logo imgs.
rx_strip_proto = re.compile("^\w+://|/$")
rx_just_domain = re.compile("^\w+://|[/#?].*$")
rx_non_wordchr = re.compile("[^\w._-]")
def row_to_fn(row):
    url = row.get("img") or row.get("homepage") or None
    url = row.get("img")
    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)  # prefix cache directory
        url = rx_strip_proto.sub("", url)     # strip proto:// and trailing /
    else:
        url = row.get("homepage")
        if url:
            url = rx_just_domain.sub("", url) # remove proto:// and any /path
    if url:
        url = url.lower()
        url = rx_non_wordchr.sub("_", url)    # remove any non-word characters
        url = "{}/{}.png".format(conf.icon_dir, url)  # prefix cache directory
    return url


    
# Copy banner row["img"] into icons/ directory
def banner_localcopy(url, fn):