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

⌈⌋ branch:  streamtuner2


Check-in [aac4fcacbf]

Overview
Comment:Implement favicon live updating. Play event and download_all now pass the treestore, with row index, and pix_entry number (column index in liststore). Favicon module checks for downloaded images twice now, and updates PixBuf in ListStore. (Works for both single station view, and download_all.)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: aac4fcacbfaafe669d49d9db4571d8c4588d4d88
User & Date: mario on 2015-05-09 21:40:07
Other Links: manifest | tags
Context
2015-05-09
21:41
Fix super slow requests download for Xiph YP.XML, due to automatic charset detected in requests.text access. Override encoding= now and manually .decode() known "utf-8" charset. check-in: 06fe0ef3db user: mario tags: trunk
21:40
Implement favicon live updating. Play event and download_all now pass the treestore, with row index, and pix_entry number (column index in liststore). Favicon module checks for downloaded images twice now, and updates PixBuf in ListStore. (Works for both single station view, and download_all.) check-in: aac4fcacbf user: mario tags: trunk
21:38
Prepare for more complex hooks["play"] invocation (ignore args, kwargs). check-in: 5fbe0ccd0c user: mario tags: trunk
Changes

Modified favicon.py from [684fc768c9] to [9ae90f0624].

30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64



65
66
67
68
69
70
71
72
73
74


















75
76
77
78
79
80
81
from compat2and3 import xrange, urllib
import re
from config import *
from threading import Thread
import ahttp
import compat2and3
from PIL import Image




# ensure that we don't try to download a single favicon twice per session,
# if it's not available the first time, we won't get it after switching stations back and forth
tried_urls = []




# walk through entries
def download_all(entries, treestore=None, pix_i=None):
  t = Thread(target= download_thread, args= ([entries]))
  t.start()
def download_thread(entries):
    for e in entries:
        # try just once
        if e.get("homepage") in tried_urls:
            continue

        # retrieve specific img url as favicon
        elif e.get("img"):
            localcopy(e["img"], True)
            continue
        # favicon from homepage URL
        elif e.get("homepage"):
            download(e["homepage"])
        # remember
        tried_urls.append(e.get("homepage"))



    pass

# download a single favicon for currently playing station
def download_playing(row, treestore_pix=None):
    if conf.google_homepage and not row.get("homepage"):
        google_find_homepage(row)
    if conf.load_favicon and row.get("homepage"):
        download_all([row])
    pass





















#--- unrelated ---
def google_find_homepage(row):
    """ Searches for missing homepage URL via Google. """
    if row.get("url") not in tried_urls:
        tried_urls.append(row.get("url"))







>











|
|

|
|



>



|



<
|
>
>
>



|



|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from compat2and3 import xrange, urllib
import re
from config import *
from threading import Thread
import ahttp
import compat2and3
from PIL import Image
from uikit import gtk



# ensure that we don't try to download a single favicon twice per session,
# if it's not available the first time, we won't get it after switching stations back and forth
tried_urls = []




# walk through entries
def download_all(*args, **kwargs):
  t = Thread(target=download_thread, args=args, kwargs=kwargs)
  t.start()
def download_thread(entries, pixstore=None):
    for i,e in enumerate(entries):
        # try just once
        if e.get("homepage") in tried_urls:
            continue

        # retrieve specific img url as favicon
        elif e.get("img"):
            localcopy(e["img"], True)
            tried_urls.append(e.get("img"))
        # favicon from homepage URL
        elif e.get("homepage"):
            download(e["homepage"])

            tried_urls.append(e.get("homepage"))

        # Update TreeView
        update_pixstore(e, pixstore, i)
    pass

# download a single favicon for currently playing station
def download_playing(row, pixstore=None):
    if conf.google_homepage and not row.get("homepage"):
        google_find_homepage(row)
    if conf.load_favicon and row.get("homepage"):
        download_all([row], pixstore=pixstore)
    pass


# Update favicon in treeview/liststore
def update_pixstore(row, pixstore=None, row_i=None):
    log.PIXSTORE(pixstore, row_i)
    if pixstore:
        ls, pix_entry, i = pixstore
        if i is None:
            i = row_i
        fn = None
        if row.get("favicon"):
            fn = row["favicon"]
        elif row.get("img"):
            fn = localcopy(row["img"], False)
        elif row.get("homepage"):
            fn = file(row["homepage"])
        if fn and os.path.exists(fn):
            p = gtk.gdk.pixbuf_new_from_file(fn)
            ls[i][pix_entry] = p


#--- unrelated ---
def google_find_homepage(row):
    """ Searches for missing homepage URL via Google. """
    if row.get("url") not in tried_urls:
        tried_urls.append(row.get("url"))

Modified st2.py from [833ae6e3d8] to [7768280a8d].

258
259
260
261
262
263
264
265


266
267
268
269
270
271
272
273
274
        return self.row().get(name)


            
    # Play button
    def on_play_clicked(self, widget, event=None, *args):
        self.status("Starting player...")
        row = self.channel().play()


        self.status("")
        [callback(row) 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()
        [callback(row) for callback in self.hooks["record"]]








|
>
>

|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
        return self.row().get(name)


            
    # Play button
    def on_play_clicked(self, widget, event=None, *args):
        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"]]

    # Recording: invoke streamripper for current stream URL
    def on_record_clicked(self, widget):
        self.status("Recording station...")
        row = self.channel().record()
        [callback(row) for callback in self.hooks["record"]]

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

    # Reload category tree
    def update_categories(self, widget):
        Thread(target=self.channel().reload_categories).start()

    # Menu invocation: refresh favicons for all stations in current streams category
    def update_favicons(self, widget):
        entries = self.channel().stations()
        favicon.download_all(entries)

    # Save stream to file (.m3u)
    def save_as(self, widget):
        row = self.row()
        default_fn = row["title"] + ".m3u"
        fn = uikit.save_file("Save Stream", None, default_fn, [(".m3u","*m3u"),(".pls","*pls"),(".xspf","*xspf"),(".jspf","*jspf"),(".smil","*smil"),(".asx","*asx"),("all files","*")])
        if fn:







|
|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336

    # Reload category tree
    def update_categories(self, widget):
        Thread(target=self.channel().reload_categories).start()

    # Menu invocation: refresh favicons for all stations in current streams category
    def update_favicons(self, widget):
        ch = self.channel()
        favicon.download_all(entries=ch.stations(), pixstore=[ch._ls, ch._pix_entry, None])

    # Save stream to file (.m3u)
    def save_as(self, widget):
        row = self.row()
        default_fn = row["title"] + ".m3u"
        fn = uikit.save_file("Save Stream", None, default_fn, [(".m3u","*m3u"),(".pls","*pls"),(".xspf","*xspf"),(".jspf","*jspf"),(".smil","*smil"),(".asx","*asx"),("all files","*")])
        if fn: