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

⌈⌋ ⎇ branch:  streamtuner2


Diff

Differences From Artifact [f927301f5f]:

To Artifact [4cf18f9328]:

  • File channels/_generic.py — part of check-in [1beab0563e] at 2014-04-10 04:31:02 on branch py3 — * Fixed gtk_list_store_get_value: assertion `column < list_store->n_columns' by removing {width:20} reference from treeview datamap. * row.setdefault() for absent search_col/set and deleted state * More __print__/dbg colorization * Disabled pson.filter_data in favour of str casting in mygtk.columns() * Removed streamactions.popup PY2/PY3 workaround with named args * More .iteritems() removal (user: mario, size: 20134) [annotate] [blame] [check-ins using]

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#  adds the required gtk Widgets manually.
#


import gtk
from mygtk import mygtk
from config import conf, __print__, dbg
import http
import action
import favicon
import os.path
import xml.sax.saxutils
import re
import copy








|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#  adds the required gtk Widgets manually.
#


import gtk
from mygtk import mygtk
from config import conf, __print__, dbg
import ahttp as http
import action
import favicon
import os.path
import xml.sax.saxutils
import re
import copy

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
        gtk_cat = None    #gtk widget

        # mapping of stream{} data into gtk treeview/treestore representation
        datamap = [
           # coltitle   width	[ datasrc key, type, renderer, attrs ]	[cellrenderer2], ...
           ["",		20,	["state",	str,  "pixbuf",	{}],	],
           ["Genre",	65,	['genre',	str,	"t",	{}],	],
           ["Station Title",275,["title",	str,    "text",	{"strikethrough":11, "cell-background":12, "cell-background-set":13}],  ["favicon",gtk.gdk.Pixbuf,"pixbuf",{"width":20}], ],
           ["Now Playing",185,	["playing",	str,	"text",	{"strikethrough":11}],	],
           ["Listeners", 45,	["listeners",	int,	"t",	{"strikethrough":11}],	],
          #["Max",	45,	["max",		int,	"t",	{}],	],
           ["Bitrate",	35,	["bitrate",	int,	"t",	{}],	],
           ["Homepage",	160,	["homepage",	str,	"t",	{"underline":10}],	],
           [False,	25,	["url",		str,	"t",	{"strikethrough":11}],	],
           [False,	0,	["format",	str,	None,	{}],	],
           [False,	0,	["favourite",	bool,	None,	{}],	],







|
|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
        gtk_cat = None    #gtk widget

        # mapping of stream{} data into gtk treeview/treestore representation
        datamap = [
           # coltitle   width	[ datasrc key, type, renderer, attrs ]	[cellrenderer2], ...
           ["",		20,	["state",	str,  "pixbuf",	{}],	],
           ["Genre",	65,	['genre',	str,	"t",	{}],	],
           ["Station Title",275,["title",	str,    "text",	{"strikethrough":11, "cell-background":12, "cell-background-set":13}],  ["favicon", gtk.gdk.Pixbuf, "pixbuf", {}], ],
           ["Now Playing",185,	["playing",	str,	"text",	{"strikethrough":11}],	],                                                                             #{"width":20}
           ["Listeners", 45,	["listeners",	int,	"t",	{"strikethrough":11}],	],
          #["Max",	45,	["max",		int,	"t",	{}],	],
           ["Bitrate",	35,	["bitrate",	int,	"t",	{}],	],
           ["Homepage",	160,	["homepage",	str,	"t",	{"underline":10}],	],
           [False,	25,	["url",		str,	"t",	{"strikethrough":11}],	],
           [False,	0,	["format",	str,	None,	{}],	],
           [False,	0,	["favourite",	bool,	None,	{}],	],
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
            self.gtk_cat = parent.get_widget(self.module+"_cat")
            
            # category tree
            self.display_categories()
            #mygtk.tree(self.gtk_cat, self.categories, title="Category", icon=gtk.STOCK_OPEN);
            
            # update column names
            for field,title in self.titles.iteritems():
                self.update_datamap(field, title=title)
            
            # prepare stream list
            if (not self.rowmap):
                for row in self.datamap:
                    for x in xrange(2, len(row)):
                        self.rowmap.append(row[x][0])

            # load default category
            if (self.current):
                self.load(self.current)
            else:
                mygtk.columns(self.gtk_list, self.datamap, [{}])







|





|







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
            self.gtk_cat = parent.get_widget(self.module+"_cat")
            
            # category tree
            self.display_categories()
            #mygtk.tree(self.gtk_cat, self.categories, title="Category", icon=gtk.STOCK_OPEN);
            
            # update column names
            for field,title in list(self.titles.items()):
                self.update_datamap(field, title=title)
            
            # prepare stream list
            if (not self.rowmap):
                for row in self.datamap:
                    for x in range(2, len(row)):
                        self.rowmap.append(row[x][0])

            # load default category
            if (self.current):
                self.load(self.current)
            else:
                mygtk.columns(self.gtk_list, self.datamap, [{}])
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

        # switch stream category,
        # load data,
        # update treeview content
        def load(self, category, force=False):
        
            # get data from cache or download
            if (force or not self.streams.has_key(category)):
                new_streams = self.update_streams(category)
      
                if new_streams:
                
                    # modify
                    [self.postprocess(row) for row in new_streams]
      







|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

        # switch stream category,
        # load data,
        # update treeview content
        def load(self, category, force=False):
        
            # get data from cache or download
            if (force or not category in self.streams):
                new_streams = self.update_streams(category)
      
                if new_streams:
                
                    # modify
                    [self.postprocess(row) for row in new_streams]
      
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

            
        # finds differences in new/old streamlist, marks deleted with flag
        def deleted_streams(self, new, old):
            diff = []
            new = [row.get("url","http://example.com/") for row in new]
            for row in old:
                if (row.has_key("url") and (row.get("url") not in new)):
                    row["deleted"] = 1
                    diff.append(row)
            return diff

        
        # prepare data for display
        def prepare(self, streams):
            for i,row in enumerate(streams):
                                            # oh my, at least it's working
                                            # at start the bookmarks module isn't fully registered at instantiation in parent.channels{} - might want to do that step by step rather
                                            # then display() is called too early to take effect - load() & co should actually be postponed to when a notebook tab gets selected first
                                            # => might be fixed now, 1.9.8
                # state icon: bookmark star
                if (conf.show_bookmarks and self.parent.channels.has_key("bookmarks") and self.parent.bookmarks.is_in(streams[i].get("url", "file:///tmp/none"))):
                    streams[i]["favourite"] = 1
                
                # state icon: INFO or DELETE
                if (not row.get("state")):
                    if row.get("favourite"):
                        streams[i]["state"] = gtk.STOCK_ABOUT
                    if conf.retain_deleted and row.get("deleted"):







|













|







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

            
        # finds differences in new/old streamlist, marks deleted with flag
        def deleted_streams(self, new, old):
            diff = []
            new = [row.get("url","http://example.com/") for row in new]
            for row in old:
                if (url in row and (row.get("url") not in new)):
                    row["deleted"] = 1
                    diff.append(row)
            return diff

        
        # prepare data for display
        def prepare(self, streams):
            for i,row in enumerate(streams):
                                            # oh my, at least it's working
                                            # at start the bookmarks module isn't fully registered at instantiation in parent.channels{} - might want to do that step by step rather
                                            # then display() is called too early to take effect - load() & co should actually be postponed to when a notebook tab gets selected first
                                            # => might be fixed now, 1.9.8
                # state icon: bookmark star
                if (conf.show_bookmarks and "bookmarks" in self.parent.channels and self.parent.bookmarks.is_in(streams[i].get("url", "file:///tmp/none"))):
                    streams[i]["favourite"] = 1
                
                # state icon: INFO or DELETE
                if (not row.get("state")):
                    if row.get("favourite"):
                        streams[i]["state"] = gtk.STOCK_ABOUT
                    if conf.retain_deleted and row.get("deleted"):
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325

            if (self.shown != 55555):
            
                # if category tree is empty, initialize it
                if not self.categories:
                    __print__(dbg.PROC, "first_show: reload_categories");
                    #self.parent.thread(self.reload_categories)
                    print("reload categories");
                    self.reload_categories()
                    self.display_categories()
                    self.current = self.categories.keys()[0]
                    print self.current
                    self.load(self.current)
            
                # load current category
                else:
                    __print__(dbg.STAT, "first_show: load current category");
                    self.load(self.current)
                







<



|







307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323
324

            if (self.shown != 55555):
            
                # if category tree is empty, initialize it
                if not self.categories:
                    __print__(dbg.PROC, "first_show: reload_categories");
                    #self.parent.thread(self.reload_categories)

                    self.reload_categories()
                    self.display_categories()
                    self.current = self.categories.keys()[0]
                    __print__(dbg.STAT, self.current)
                    self.load(self.current)
            
                # load current category
                else:
                    __print__(dbg.STAT, "first_show: load current category");
                    self.load(self.current)