Index: _package.epm ================================================================== --- _package.epm +++ _package.epm @@ -88,10 +88,12 @@ f 644 root root /usr/share/doc/streamtuner2/help/channel_internetradioorguk.page ./help/channel_internetradioorguk.page f 644 root root /usr/share/doc/streamtuner2/help/channel_jamendo.page ./help/channel_jamendo.page f 644 root root /usr/share/doc/streamtuner2/help/channel_myoggradio.page ./help/channel_myoggradio.page f 644 root root /usr/share/doc/streamtuner2/help/channel_shoutcast.page ./help/channel_shoutcast.page f 644 root root /usr/share/doc/streamtuner2/help/channel_xiph.page ./help/channel_xiph.page +f 644 root root /usr/share/doc/streamtuner2/help/channel_youtube.page ./help/channel_youtube.page +f 644 root root /usr/share/doc/streamtuner2/help/channel_surfmusik.page ./help/channel_surfmusik.page f 644 root root /usr/share/doc/streamtuner2/help/channels.page ./help/channels.page f 644 root root /usr/share/doc/streamtuner2/help/cli.page ./help/cli.page f 644 root root /usr/share/doc/streamtuner2/help/config_apps.page ./help/config_apps.page f 644 root root /usr/share/doc/streamtuner2/help/configuration.page ./help/configuration.page f 644 root root /usr/share/doc/streamtuner2/help/extending.page ./help/extending.page Index: channels/itunes.py ================================================================== --- channels/itunes.py +++ channels/itunes.py @@ -78,11 +78,11 @@ # static list for iTunes def update_categories(self): pass # Just copy over stream URLs and station titles - def update_streams(self, cat, search=None): + def update_streams(self, cat): m3u = http.get(self.base, {"category": cat.lower()}) if len(m3u) < 256: __print__(dbg.ERR, m3u) Index: channels/live365.py ================================================================== --- channels/live365.py +++ channels/live365.py @@ -36,10 +36,11 @@ # desc module = "live365" title = "Live365" homepage = "http://www.live365.com/" base_url = "http://www.live365.com/" + has_search = True listformat = "url/http" mediatype = "audio/mpeg" # content categories = ['Alternative', ['Britpop', 'Classic Alternative', 'College', 'Dancepunk', 'Dream Pop', 'Emo', 'Goth', 'Grunge', 'Indie Pop', 'Indie Rock', 'Industrial', 'Lo-Fi', 'Modern Rock', 'New Wave', 'Noise Pop', 'Post-Punk', 'Power Pop', 'Punk'], 'Blues', ['Acoustic Blues', 'Chicago Blues', 'Contemporary Blues', 'Country Blues', 'Delta Blues', 'Electric Blues', 'Cajun/Zydeco'], 'Classical', ['Baroque', 'Chamber', 'Choral', 'Classical Period', 'Early Classical', 'Impressionist', 'Modern', 'Opera', 'Piano', 'Romantic', 'Symphony'], 'Country', ['Alt-Country', 'Americana', 'Bluegrass', 'Classic Country', 'Contemporary Bluegrass', 'Contemporary Country', 'Honky Tonk', 'Hot Country Hits', 'Western'], 'Easy Listening', ['Exotica', 'Lounge', 'Orchestral Pop', 'Polka', 'Space Age Pop'], 'Electronic/Dance', ['Acid House', 'Ambient', 'Big Beat', 'Breakbeat', 'Disco', 'Downtempo', "Drum 'n' Bass", 'Electro', 'Garage', 'Hard House', 'House', 'IDM', 'Jungle', 'Progressive', 'Techno', 'Trance', 'Tribal', 'Trip Hop'], 'Folk', ['Alternative Folk', 'Contemporary Folk', 'Folk Rock', 'New Acoustic', 'Traditional Folk', 'World Folk'], 'Freeform', ['Chill', 'Experimental', 'Heartache', 'Love/Romance', 'Music To ... To', 'Party Mix', 'Patriotic', 'Rainy Day Mix', 'Reality', 'Shuffle/Random', 'Travel Mix', 'Trippy', 'Various', 'Women', 'Work Mix'], 'Hip-Hop/Rap', ['Alternative Rap', 'Dirty South', 'East Coast Rap', 'Freestyle', 'Gangsta Rap', 'Old School', 'Turntablism', 'Underground Hip-Hop', 'West Coast Rap'], 'Inspirational', ['Christian', 'Christian Metal', 'Christian Rap', 'Christian Rock', 'Classic Christian', 'Contemporary Gospel', 'Gospel', 'Praise/Worship', 'Sermons/Services', 'Southern Gospel', 'Traditional Gospel'], 'International', ['African', 'Arabic', 'Asian', 'Brazilian', 'Caribbean', 'Celtic', 'European', 'Filipino', 'Greek', 'Hawaiian/Pacific', 'Hindi', 'Indian', 'Japanese', 'Jewish', 'Mediterranean', 'Middle Eastern', 'North American', 'Soca', 'South American', 'Tamil', 'Worldbeat', 'Zouk'], 'Jazz', ['Acid Jazz', 'Avant Garde', 'Big Band', 'Bop', 'Classic Jazz', 'Cool Jazz', 'Fusion', 'Hard Bop', 'Latin Jazz', 'Smooth Jazz', 'Swing', 'Vocal Jazz', 'World Fusion'], 'Latin', ['Bachata', 'Banda', 'Bossa Nova', 'Cumbia', 'Latin Dance', 'Latin Pop', 'Latin Rap/Hip-Hop', 'Latin Rock', 'Mariachi', 'Merengue', 'Ranchera', 'Salsa', 'Tango', 'Tejano', 'Tropicalia'], 'Metal', ['Extreme Metal', 'Heavy Metal', 'Industrial Metal', 'Pop Metal/Hair', 'Rap Metal'], 'New Age', ['Environmental', 'Ethnic Fusion', 'Healing', 'Meditation', 'Spiritual'], 'Oldies', ['30s', '40s', '50s', '60s', '70s', '80s', '90s'], 'Pop', ['Adult Contemporary', 'Barbershop', 'Bubblegum Pop', 'Dance Pop', 'JPOP', 'Soft Rock', 'Teen Pop', 'Top 40', 'World Pop'], 'R&B/Urban', ['Classic R&B', 'Contemporary R&B', 'Doo Wop', 'Funk', 'Motown', 'Neo-Soul', 'Quiet Storm', 'Soul', 'Urban Contemporary'], 'Reggae', ['Contemporary Reggae', 'Dancehall', 'Dub', 'Pop-Reggae', 'Ragga', 'Reggaeton', 'Rock Steady', 'Roots Reggae', 'Ska'], 'Rock', ['Adult Album Alternative', 'British Invasion', 'Classic Rock', 'Garage Rock', 'Glam', 'Hard Rock', 'Jam Bands', 'Prog/Art Rock', 'Psychedelic', 'Rock & Roll', 'Rockabilly', 'Singer/Songwriter', 'Surf'], 'Seasonal/Holiday', ['Anniversary', 'Birthday', 'Christmas', 'Halloween', 'Hanukkah', 'Honeymoon', 'Valentine', 'Wedding'], 'Soundtracks', ['Anime', "Children's/Family", 'Original Score', 'Showtunes'], 'Talk', ['Comedy', 'Community', 'Educational', 'Government', 'News', 'Old Time Radio', 'Other Talk', 'Political', 'Scanner', 'Spoken Word', 'Sports']] @@ -95,17 +96,18 @@ self.categories.append(last) # extract stream infos - def update_streams(self, cat, search=""): + def update_streams(self, cat, search=None): - # search / url - if (not search): - url = "http://www.live365.com/cgi-bin/directory.cgi?first=1&rows=200&mode=2&genre=" + self.cat2tag(cat) + # search + if search: + url = "http://www.live365.com/cgi-bin/directory.cgi?site=..&searchdesc=" + urllib.quote(search) + "&searchgenre=" + self.cat2tag(cat) + "&x=0&y=0" + # genre else: - url = "http://www.live365.com/cgi-bin/directory.cgi?site=..&searchdesc=" + urllib.quote(search) + "&searchgenre=" + self.cat2tag(cat) + "&x=0&y=0" + url = "http://www.live365.com/cgi-bin/directory.cgi?first=1&rows=200&mode=2&genre=" + self.cat2tag(cat) html = http.get(url, feedback=self.parent.status) # we only need to download one page, because live365 always only gives 200 results # terse format rx = re.compile(r""" Index: channels/musicgoal.py ================================================================== --- channels/musicgoal.py +++ channels/musicgoal.py @@ -56,11 +56,11 @@ def update_categories(self): pass # request json API - def update_streams(self, cat, search=""): + def update_streams(self, cat): # category type: podcast or radio if cat in self.podcast: grp = "podcast" url = self.api_podcast % (grp, self.podcast.index(cat)+1) Index: channels/shoutcast.py ================================================================== --- channels/shoutcast.py +++ channels/shoutcast.py @@ -87,11 +87,11 @@ conf.save("cache/categories_shoutcast", self.categories) pass # downloads stream list from shoutcast for given category - def update_streams(self, cat, search=""): + def update_streams(self, cat): if (not cat or cat == self.empty): __print__( dbg.ERR, "nocat" ) return [] Index: channels/xiph.py ================================================================== --- channels/xiph.py +++ channels/xiph.py @@ -84,11 +84,11 @@ def update_categories(self): pass # downloads stream list from xiph.org for given category - def update_streams(self, cat, search=""): + def update_streams(self, cat, search=None): # With the new JSON cache API on I-O, we can load categories individually: params = {} if cat: params["cat"] = cat.lower() Index: channels/youtube.py ================================================================== --- channels/youtube.py +++ channels/youtube.py @@ -1,15 +1,14 @@ # encoding: UTF-8 # api: streamtuner2 # title: Youtube # description: Channel, playlist and video browsing for youtube. # type: channel -# version: 0.1 +# version: 0.2 # category: video # priority: optional # suggests: youtube-dl -# requires: ahttp # # # Lists recently popular youtube videos by category or channels. # # Introduces the faux MIME type "video/youtube" for player and recording @@ -184,11 +183,11 @@ channels = self.categories[self.categories.index("my channels") + 1] # plain search request for videos if search is not None: for row in self.api("search", type="video", regionCode=conf.youtube_region, q=search): - entries.append( self.wrap3(row, {"genre": "Youtube"}) ) + entries.append( self.wrap3(row, {"genre": ""}) ) # Most Popular elif cat == "mostPopular": #for row in self.api("feeds/api/standardfeeds/%s/most_popular"%conf.youtube_region, ver=2): # entries.append(self.wrap2(row)) Index: gtk2.xml ================================================================== --- gtk2.xml +++ gtk2.xml @@ -1078,18 +1078,19 @@ True False gtk-add + 325 False 5 station search center-on-parent + True dialog - False center - 0.95999999999999996 + 0.94999999999999996 True @@ -1147,13 +1148,14 @@ True False - + True False + 10 for True True @@ -1179,11 +1181,11 @@ True 1 - + True False True @@ -1197,11 +1199,65 @@ True 2 - + + True + False + + + True + False + 10 + 10 + in + + + True + True + 0 + + + + + all channels + True + True + False + True + True + search_dialog_current + + + True + True + 1 + + + + + just current + True + True + False + True + True + search_dialog_all + + + True + True + 2 + + + + + True + True + 3 + @@ -1212,13 +1268,11 @@ Cache _find True False - True - True - True + False Start searching for above search term in the currently loaded station lists. Doesn't find *new* information, just looks through the known data. image1 half True @@ -1233,10 +1287,14 @@ Server _search True False + True + True + True + True True Instead of doing a cache search, go through the search functions on the directory service homepages. (UNIMPLEMENTED) image2 True @@ -1344,11 +1402,12 @@ False 5 normal - + + True False 2 @@ -1397,10 +1456,100 @@ True False 3 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1841,10 +1990,25 @@ + + + + + + + + + + + + + + + True True 1 @@ -1905,12 +2069,12 @@ False 5 inspect/edit stream data center-on-parent + True True - False 0.94999999999999996 True @@ -2288,12 +2452,12 @@ True False bookmark True - + @@ -2300,12 +2464,12 @@ gtk-save-as True False True True - + @@ -2312,13 +2476,13 @@ gtk-edit True False True True - + - + @@ -2387,12 +2551,12 @@ gtk-delete True False True True - + Index: gtk3.xml ================================================================== --- gtk3.xml +++ gtk3.xml @@ -1067,17 +1067,18 @@ True False gtk-add + 325 False - 0.95999999999999996 + 0.94999999999999996 5 station search center-on-parent + True dialog - False center @@ -1136,13 +1137,14 @@ True False - + True False + 10 for True True @@ -1166,11 +1168,11 @@ True 1 - + True False True @@ -1184,11 +1186,67 @@ True 2 - + + True + False + + + True + False + 10 + 10 + in + + + True + True + 0 + + + + + all channels + True + True + False + 0.5 + True + True + search_dialog_current + + + True + True + 1 + + + + + just current + True + True + False + 0.5 + True + True + search_dialog_all + + + True + True + 2 + + + + + True + True + 3 + @@ -1199,13 +1257,11 @@ Cache _find True False - True - True - True + False Start searching for above search term in the currently loaded station lists. Doesn't find *new* information, just looks through the known data. image1 half True @@ -1220,10 +1276,14 @@ Server _search True False + True + True + True + True True Instead of doing a cache search, go through the search functions on the directory service homepages. (UNIMPLEMENTED) image2 True @@ -1331,11 +1391,12 @@ False 5 normal - + + True False 2 @@ -1384,10 +1445,100 @@ True False 3 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1847,10 +1998,25 @@ + + + + + + + + + + + + + + + True True 1 @@ -1912,12 +2078,12 @@ False 0.94999999999999996 5 inspect/edit stream data center-on-parent + True True - False True False @@ -2274,12 +2440,12 @@ True False bookmark True - + gtk-save-as @@ -2286,12 +2452,12 @@ True False True True - + gtk-edit @@ -2298,13 +2464,13 @@ True False True True - + - + True @@ -2373,12 +2539,12 @@ True False True True - + gtk-find Index: help/search.page ================================================================== --- help/search.page +++ help/search.page @@ -23,27 +23,28 @@
Search window

You can get to the search dialog via Edit Find or Ctrl+F. Centrally to this dialog is the text field, where you can specify the phrase to scan for.

-

Above you can check which channel plugins to inspect for the search term. Using this + + +

And then there are two search methods. You mostly want to use + the live Server search. It passes your search terms to + the actual directory services, and loads the most recent data into a + result list (this might take a few seconds). It's not implemented + for all channel plugins however.

+ +

With Cache find would just look up entries in your + already downloaded channel/genre lists. Since often you are just + looking for something you had already seen, this will give you the + desired results.

Index: st2.py ================================================================== --- st2.py +++ st2.py @@ -585,10 +585,11 @@ # show search dialog def menu_search(self, w): self.search_dialog.show(); + self.search_dialog_current.set_label("just %s" % main.current_channel) # hide dialog box again def cancel(self, *args): self.search_dialog.hide() @@ -598,34 +599,32 @@ # prepare variables def prepare_search(self): main.status("Searching... Stand back.") self.cancel() self.q = self.search_full.get_text().lower() + if self.search_dialog_all.get_active(): + self.targets = main.channels.keys() + else: + self.targets = [main.current_channel] main.bookmarks.streams["search"] = [] # perform search def cache_search(self, *w): self.prepare_search() entries = [] # which fields? fields = ["title", "playing", "homepage"] - #if not self.search_in_all.get_active(): - # fields = [f for f in fields if (main.get_widget("search_in_"+f) and main.get_widget("search_in_"+f).get_active())] - # channels? - channels = main.channel_names[:] - #if not self.search_channel_all.get_active(): - # channels = [c for c in channels if main.get_widget("search_channel_"+c).get_active()] - for c in channels: - if main.channels[c] and main.channels[c].streams: # skip disabled plugins + for i,cn in enumerate([main.channels[c] for c in self.targets]): + if cn.streams: # skip disabled plugins # categories - for cat in main.channels[c].streams.keys(): + for cat in cn.streams.keys(): # stations - for row in main.channels[c].streams[cat]: + for row in cn.streams[cat]: # assemble text fields to compare text = " ".join([row.get(f, " ") for f in fields]) if text.lower().find(self.q) >= 0: - row["genre"] = c + " " + row["genre"] + row["genre"] = c + " " + row.get("genre", "") entries.append(row) self.show_results(entries) # display "search" in "bookmarks" def show_results(self, entries): @@ -639,21 +638,21 @@ # live search on directory server homepages def server_search(self, w): self.prepare_search() entries = [] - for i,cn in enumerate([main.channels[c] for c in main.channels]): -# main.status(main, 1.0 * i / 15) - if cn.has_search: + for i,cn in enumerate([main.channels[c] for c in self.targets]): + if cn.has_search: # "search" in cn.update_streams.func_code.co_varnames: __print__(dbg.PROC, "has_search:", cn.module) try: add = cn.update_streams(cat=None, search=self.q) for row in add: - row["genre"] = cn.title + " " + row["genre"] + row["genre"] = cn.title + " " + row.get("genre", "") entries += add except: continue + #main.status(main, 1.0 * i / 15) self.show_results(entries) # search text edited in text entry box def quicksearch_set(self, w, *eat, **up):