Index: channels/__init__.py ================================================================== --- channels/__init__.py +++ channels/__init__.py @@ -572,12 +572,5 @@ GenericChannel.gui(self, parent) # add notebook tab tab = parent.notebook_channels.insert_page_menu(vbox, ev_label, plain_label, -1) - # double-click catch - - # add module to list - #parent.channels[module] = None - #parent.channel_names.append(module) - """ -> already taken care of in main.load_plugins() """ - Index: channels/bookmarks.py ================================================================== --- channels/bookmarks.py +++ channels/bookmarks.py @@ -33,177 +33,176 @@ # # It's accessible as `main.bookmarks` in the ST2 window and elsewhere. # class bookmarks(GenericChannel): -# desc -module = "bookmarks" -title = "bookmarks" -base_url = "file:.config/streamtuner2/bookmarks.json" -listformat = "*/*" - -# content -categories = ["favourite", ] # timer, links, search, and links show up as needed -current = "favourite" -default = "favourite" -streams = {"favourite":[], "search":[], "scripts":[], "timer":[], "history":[], } - - -# cache list, to determine if a PLS url is bookmarked -urls = [] - - - -def gui(self, parent): - GenericChannel.gui(self, parent) - parent.notebook_channels.set_menu_label_text(parent.v_bookmarks, "bookmarks") - - -# this channel does not actually retrieve/parse data from anywhere -def update_categories(self): - pass - -# but category sub-plugins might provide a hook -category_plugins = {} -def update_streams(self, cat): - if cat in self.category_plugins: - return self.category_plugins[cat].update_streams(cat) or [] - else: - return self.streams.get(cat, []) - - -# streams are already loaded at instantiation -def first_show(self): - pass - - -# all entries just come from "bookmarks.json" -def cache(self): - # stream list - cache = conf.load(self.module) - if (cache): - __print__(dbg.PROC, "load bookmarks.json") - self.streams = cache - - - -# save to cache file -def save(self): - conf.save(self.module, self.streams, nice=1) - - -# checks for existence of an URL in bookmarks store, -# this method is called by other channel modules' display() method -def is_in(self, url, once=1): - if (not self.urls): - self.urls = [row.get("url","urn:x-streamtuner2:no") for row in self.streams["favourite"]] - return url in self.urls - - -# called from main window / menu / context menu, -# when bookmark is to be added for a selected stream entry -def add(self, row): - - # normalize data (this row originated in a gtk+ widget) - row["favourite"] = 1 - if row.get("favicon"): - row["favicon"] = favicon.file(row.get("homepage")) - if not row.get("listformat"): - row["listformat"] = main.channel().listformat - - # append to storage - self.streams["favourite"].append(row) - self.save() - self.load(self.default) - self.urls.append(row["url"]) - - -# simplified gtk TreeStore display logic (just one category for the moment, always rebuilt) -def load(self, category, force=False): - __print__(dbg.UI, category, self.streams.keys()) - self.streams[category] = self.update_streams(category) - #self.liststore[category] = \ - uikit.columns(self.gtk_list, self.datamap, self.prepare(self.streams[category])) - - -# add a categories[]/streams{} subcategory, update treeview -def add_category(self, cat, plugin=None): - if cat not in self.categories: # add category if missing - self.categories.append(cat) - self.display_categories() - if cat not in self.streams: - self.streams[cat] = [] - if plugin: - self.category_plugins[cat] = plugin - - -# change cursor -def set_category(self, cat): - self.add_category(cat) - self.gtk_cat.get_selection().select_path(str(self.categories.index(cat))) - return self.currentcat() - - -# update bookmarks from freshly loaded streams data -def heuristic_update(self, updated_channel, updated_category): - - if not conf.heuristic_bookmark_update: return - __print__(dbg.ERR, "heuristic bookmark update") - save = 0 - fav = self.streams["favourite"] - - # First we'll generate a list of current bookmark stream urls, and then - # remove all but those from the currently UPDATED_channel + category. - # This step is most likely redundant, but prevents accidently re-rewriting - # stations that are in two channels (=duplicates with different PLS urls). - check = {"http//": "[row]"} - check = dict((row.get("url", "http//"),row) for row in fav) - # walk through all channels/streams - for chname,channel in main.channels.items(): - for cat,streams in channel.streams.items(): - - # keep the potentially changed rows - if (chname == updated_channel) and (cat == updated_category): - freshened_streams = streams - - # remove unchanged urls/rows - else: - unchanged_urls = (row.get("url") for row in streams) - for url in unchanged_urls: - if url in check: - del check[url] - # directory duplicates could unset the check list here, - # so we later end up doing a deep comparison - - - # now the real comparison, - # where we compare station titles and homepage url to detect if a bookmark is an old entry - for row in freshened_streams: - url = row.get("url") - - # empty entry (google stations), or stream still in current favourites - if not url or url in check: - pass - - # need to search - else: - title = row.get("title") - homepage = row.get("homepage") - for i,old in enumerate(fav): - - # skip if new url already in streams - if url == old.get("url"): - pass # This is caused by channel duplicates with identical PLS links. - - # on exact matches (but skip if url is identical anyway) - elif title == old["title"] and homepage == old.get("homepage",homepage): - # update stream url - fav[i]["url"] = url - save = 1 - - # more text similarity heuristics might go here - else: - pass - - # if there were changes - if save: self.save() + # desc + module = "bookmarks" + title = "bookmarks" + base_url = "file:.config/streamtuner2/bookmarks.json" + listformat = "*/*" + + # content + categories = ["favourite", ] # timer, links, search, and links show up as needed + current = "favourite" + default = "favourite" + streams = {"favourite":[], "search":[], "scripts":[], "timer":[], "history":[], } + + + # cache list, to determine if a PLS url is bookmarked + urls = [] + + + def gui(self, parent): + GenericChannel.gui(self, parent) + parent.notebook_channels.set_menu_label_text(parent.v_bookmarks, "bookmarks") + + + # this channel does not actually retrieve/parse data from anywhere + def update_categories(self): + pass + + # but category sub-plugins might provide a hook + category_plugins = {} + def update_streams(self, cat): + if cat in self.category_plugins: + return self.category_plugins[cat].update_streams(cat) or [] + else: + return self.streams.get(cat, []) + + + # streams are already loaded at instantiation + def first_show(self): + pass + + + # all entries just come from "bookmarks.json" + def cache(self): + # stream list + cache = conf.load(self.module) + if (cache): + __print__(dbg.PROC, "load bookmarks.json") + self.streams = cache + + + + # save to cache file + def save(self): + conf.save(self.module, self.streams, nice=1) + + + # checks for existence of an URL in bookmarks store, + # this method is called by other channel modules' display() method + def is_in(self, url, once=1): + if (not self.urls): + self.urls = [row.get("url","urn:x-streamtuner2:no") for row in self.streams["favourite"]] + return url in self.urls + + + # called from main window / menu / context menu, + # when bookmark is to be added for a selected stream entry + def add(self, row): + + # normalize data (this row originated in a gtk+ widget) + row["favourite"] = 1 + if row.get("favicon"): + row["favicon"] = favicon.file(row.get("homepage")) + if not row.get("listformat"): + row["listformat"] = main.channel().listformat + + # append to storage + self.streams["favourite"].append(row) + self.save() + self.load(self.default) + self.urls.append(row["url"]) + + + # simplified gtk TreeStore display logic (just one category for the moment, always rebuilt) + def load(self, category, force=False): + __print__(dbg.UI, category, self.streams.keys()) + self.streams[category] = self.update_streams(category) + #self.liststore[category] = \ + uikit.columns(self.gtk_list, self.datamap, self.prepare(self.streams[category])) + + + # add a categories[]/streams{} subcategory, update treeview + def add_category(self, cat, plugin=None): + if cat not in self.categories: # add category if missing + self.categories.append(cat) + self.display_categories() + if cat not in self.streams: + self.streams[cat] = [] + if plugin: + self.category_plugins[cat] = plugin + + + # change cursor + def set_category(self, cat): + self.add_category(cat) + self.gtk_cat.get_selection().select_path(str(self.categories.index(cat))) + return self.currentcat() + + + # update bookmarks from freshly loaded streams data + def heuristic_update(self, updated_channel, updated_category): + + if not conf.heuristic_bookmark_update: return + __print__(dbg.ERR, "heuristic bookmark update") + save = 0 + fav = self.streams["favourite"] + + # First we'll generate a list of current bookmark stream urls, and then + # remove all but those from the currently UPDATED_channel + category. + # This step is most likely redundant, but prevents accidently re-rewriting + # stations that are in two channels (=duplicates with different PLS urls). + check = {"http//": "[row]"} + check = dict((row.get("url", "http//"),row) for row in fav) + # walk through all channels/streams + for chname,channel in main.channels.items(): + for cat,streams in channel.streams.items(): + + # keep the potentially changed rows + if (chname == updated_channel) and (cat == updated_category): + freshened_streams = streams + + # remove unchanged urls/rows + else: + unchanged_urls = (row.get("url") for row in streams) + for url in unchanged_urls: + if url in check: + del check[url] + # directory duplicates could unset the check list here, + # so we later end up doing a deep comparison + + + # now the real comparison, + # where we compare station titles and homepage url to detect if a bookmark is an old entry + for row in freshened_streams: + url = row.get("url") + + # empty entry (google stations), or stream still in current favourites + if not url or url in check: + pass + + # need to search + else: + title = row.get("title") + homepage = row.get("homepage") + for i,old in enumerate(fav): + + # skip if new url already in streams + if url == old.get("url"): + pass # This is caused by channel duplicates with identical PLS links. + + # on exact matches (but skip if url is identical anyway) + elif title == old["title"] and homepage == old.get("homepage",homepage): + # update stream url + fav[i]["url"] = url + save = 1 + + # more text similarity heuristics might go here + else: + pass + + # if there were changes + if save: self.save() Index: channels/search.py ================================================================== --- channels/search.py +++ channels/search.py @@ -32,11 +32,11 @@ # either current channel, or last channel (avoid searching in bookmarks) current = None # show search dialog def menu_search(self, w): - self.search_dialog.show(); + self.search_dialog.show_all(); if not self.current or self.main.current_channel != "bookmarks": self.current = self.main.current_channel self.search_dialog_current.set_label("just %s" % self.main.channels[self.current].meta["title"]) Index: help/streamtuner2.1 ================================================================== --- help/streamtuner2.1 +++ help/streamtuner2.1 @@ -1,8 +1,8 @@ .\" (many thanks to the manpage howto!) .\" -.TH streamtuner2 1 "2015-02-07" "2.1.4" "Application manuals" +.TH streamtuner2 1 "2015-04-02" "2.1.4" "Application manuals" .SH NAME streamtuner2 \- Browser for internet radio stations .SH SYNOPSIS .B streamtuner2 .I command