Check-in [fff3b62827]
Comment: | Completer plugin meta data blocks, now utilized in channel settings dialog for nicer descriptions. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
fff3b62827ca4703be7a50f5660c2118 |
User & Date: | mario on 2014-05-13 16:23:02 |
Other Links: | manifest | tags |
2014-05-13
| ||
18:16 | Fix missing mygtk import check-in: 2ccad59967 user: mario tags: trunk | |
16:23 | Completer plugin meta data blocks, now utilized in channel settings dialog for nicer descriptions. check-in: fff3b62827 user: mario tags: trunk | |
03:26 | Make config.pyquery and config.debug global options. check-in: 3b842c85a3 user: mario tags: trunk | |
Modified channels/__init__.py from [92d73c2e69] to [1d725c2e92].
1 2 3 4 5 | # # encoding: UTF-8 # api: python # type: R # | > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 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 | # # encoding: UTF-8 # api: streamtuner2 # title: Plugin handling # description: Channels and feature plugins reside in channels/ # api: python # type: R # category: core # priority: core # # # # # # from channels._generic import * # Only reexport plugin classes __all__ = [ "GenericChannel", "ChannelPlugin" ] # Search through ./channels/ and get module basenames. # Also order them by conf.channel_order # def module_list(): # find plugin files ls = os.listdir(conf.share + "/channels/") ls = [fn[:-3] for fn in ls if re.match("^[a-z][\w\d_]+\.py$", fn)] # resort with tab order order = [module.strip() for module in conf.channel_order.lower().replace(".","_").replace("-","_").split(",")] ls = [module for module in (order) if (module in ls)] + [module for module in (ls) if (module not in order)] return ls # Parse plugin comment blocks. # def module_meta(): meta = {} rx_meta = re.compile(r"""^#\s*(\w+):\s*(.+)$""", re.M) # Loop through all existing module.py scripts for name in module_list(): meta[name] = dict(title="", type="", description="") # Read and regex-extract into dict with open("%s/channels/%s.py" % (conf.share, name)) as f: for field in re.findall(rx_meta, f.read(1024)): meta[name][field[0]] = field[1] return meta |
Modified channels/_generic.py from [740afe7476] to [3af550db05].
1 2 3 | # # encoding: UTF-8 # api: streamtuner2 | | > | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # # encoding: UTF-8 # api: streamtuner2 # type: internal # category: ui # title: channel objects # description: base functionality for channel modules # version: 1.1 # author: mario # license: public domain # priority: core # # # GenericChannel implements the basic GUI functions and defines # the default channel data structure. It implements base and # fallback logic for all other channel implementations. # # Built-in channels derive directly from generic. Additional |
︙ | ︙ | |||
41 42 43 44 45 46 47 | pass # generic channel module --------------------------------------- class GenericChannel(object): # desc | < < | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | pass # generic channel module --------------------------------------- class GenericChannel(object): # desc module = "generic" title = "GenericChannel" homepage = "http://milki.inlcude-once.org/streamtuner2/" base_url = "" listformat = "audio/x-scpls" audioformat = "audio/mp3" # fallback value config = [] has_search = False |
︙ | ︙ |
Modified channels/file.py from [13559afbce] to [a8e2e93dda].
1 2 | # # api: streamtuner2 | | | > > | > < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # # api: streamtuner2 # title: File browser # description: Displays mp3/oggs or m3u/pls files from local media file directories. # type: channel # category: media # version: 0.0 # priority: optional # depends: mutagen, kiwi # # # Local file browser. # # |
︙ | ︙ |
Modified channels/global_key.py from [3bfb69eda6] to [3a244b8b88].
1 | # | < | | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # # api: streamtuner2 # title: Global keyboard shortcut # description: Allows switching between bookmarked radios via key press. # type: feature # category: ui # version: 0.2 # priority: extra # depends: python-keybinder # # # Binds a key to global desktop (F13 = left windows key). On keypress # it switches the currently playing radio station to another one in # bookmarks list. # |
︙ | ︙ | |||
23 24 25 26 27 28 29 | # register a key class global_key(object): module = "global_key" title = "keyboard shortcut" | < | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # register a key class global_key(object): module = "global_key" title = "keyboard shortcut" config = [ dict(name="switch_key", type="text", value="XF86Forward", description="global key for switching radio"), dict(name="switch_channel", type="text", value="bookmarks:favourite", description="station list to alternate in"), dict(name="switch_random", type="boolean", value=0, description="pick random channel, instead of next"), ] last = 0 |
︙ | ︙ |
Modified channels/google.py from [40a11acd81] to [67db911f9e].
1 2 3 | # # encoding: ISO-8859-1 # api: streamtuner2 | | | | > > | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # # encoding: ISO-8859-1 # api: streamtuner2 # title: Google stations # description: Looks up web radio homepages from DMOZ/Google directory. # type: channel # category: web # priority: deprecated # version: 0.2 # depends: channels, re, http # author: Mario, original: Jean-Yves Lefort # # This is a plugun from streamtuner1. It has been rewritten for the # more mundane plugin API of streamtuner2 - reimplementing ST seemed # to much work. # Also it has been rewritten to query DMOZ directly. Google required # the use of fake User-Agents for access, and the structure on DMOZ |
︙ | ︙ | |||
78 79 80 81 82 83 84 | # Google Stations is actually now DMOZ Stations class google(ChannelPlugin): # description title = "Google" module = "google" homepage = GOOGLE_STATIONS_HOME | < | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | # Google Stations is actually now DMOZ Stations class google(ChannelPlugin): # description title = "Google" module = "google" homepage = GOOGLE_STATIONS_HOME # config data config = [ # {"name": "theme", "type": "text", "value":"Tactile", "description":"Streamtuner2 theme; no this isn't a google-specific option. But you know, the plugin options are a new toy."}, # {"name": "flag2", "type": "boolean", "value":1, "description":"oh see, an unused checkbox"} ] |
︙ | ︙ |
Modified channels/internet_radio_org_uk.py from [6c77259f65] to [2ca4dac6b1].
1 2 | # # api: streamtuner2 | | | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # # api: streamtuner2 # title: Internet-Radio.org.uk # description: Broad list of webradios from all genres. # type: channel # category: radio # version: 0.1 # priority: standard # # # Might become new main plugin # # # |
︙ | ︙ | |||
25 26 27 28 29 30 31 | class internet_radio_org_uk (ChannelPlugin): # description title = "InternetRadio" module = "internet_radio_org_uk" homepage = "http://www.internet-radio.org.uk/" | < | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | class internet_radio_org_uk (ChannelPlugin): # description title = "InternetRadio" module = "internet_radio_org_uk" homepage = "http://www.internet-radio.org.uk/" listformat = "audio/x-scpls" # settings config = [ {"name":"internetradio_max_pages", "type":"int", "value":5, "description":"How many pages to fetch and read."}, ] |
︙ | ︙ |
Modified channels/jamendo.py from [d8e3335952] to [5fc1148fae].
1 2 | # api: streamtuner2 | | | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # api: streamtuner2 # title: Jamendo # description: A license-free music collection and artist hub. # type: channel # category: radio # depends: json # priority: default # # Now utilizes the Jamendo /v3.0/ API. # # Radio station lists are fixed for now. Querying the API twice per station # doesn't seem overly sensible. # # Albums and Playlists are limited to 200 entries. Adding a cursor is |
︙ | ︙ |
Modified channels/links.py from [e2e193464a] to [a17530466f].
1 2 | # # api: streamtuner2 | | | > > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # # api: streamtuner2 # title: Links to directory services # description: Static list of various music directory websites. # type: category # category: web # version: 0.1 # priority: default # # # Simply adds a "links" entry in bookmarks tab, where known channels # and some others are listed with homepage links. # # |
︙ | ︙ |
Modified channels/live365.py from [10562bd5f9] to [cd7a2a9078].
|
| > | | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # api: streamtunter2 # title: Live365 # description: Around 5000 categorized internet radio streams, some paid ad-free ones. # type: channel # category: radio # version: 0.2 # priority: optional # # 2.0.9 fixed by Abhisek Sanyal # |
︙ | ︙ | |||
24 25 26 27 28 29 30 | # channel live365 class live365(ChannelPlugin): # desc | < < | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | # channel live365 class live365(ChannelPlugin): # desc module = "live365" title = "Live365" homepage = "http://www.live365.com/" base_url = "http://www.live365.com/" 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']] |
︙ | ︙ |
Modified channels/modarchive.py from [a906bb560c] to [7c7eb2da06].
1 2 | # api: streamtuner2 | | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # api: streamtuner2 # title: MODarchive # description: Collection of module / tracker audio files (MOD, S3M, XM, etc.) # type: channel # version: 0.1 # priority: extra # category: media # # # Just a genre browser. # # MOD files dodn't work with all audio players. And with the default # download method, it'll receive a .zip archive with embeded .mod file. # VLC in */* seems to work fine however. |
︙ | ︙ | |||
34 35 36 37 38 39 40 | # MODs class modarchive (ChannelPlugin): # description title = "modarchive" module = "modarchive" homepage = "http://www.modarchive.org/" | < | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | # MODs class modarchive (ChannelPlugin): # description title = "modarchive" module = "modarchive" homepage = "http://www.modarchive.org/" base = "http://modarchive.org/" # keeps category titles->urls catmap = {} categories = [] |
︙ | ︙ |
Modified channels/musicgoal.py from [487d9e3db3] to [3d5f5c99cc].
1 2 | # # api: streamtuner2 | | | > > > < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # # api: streamtuner2 # title: MUSICGOAL # description: Broad list of radio stations and podcasts. Provides a sane API, but only 5 results each. # type: channel # category: radio # version: 0.1 # priority: optional # status: experimental # # Musicgoal.com is a radio and podcast directory. This plugin tries to use # the new API for accessing listing data. # # |
︙ | ︙ | |||
28 29 30 31 32 33 34 | # I wonder what that is for --------------------------------------- class musicgoal (ChannelPlugin): # desc module = "musicgoal" title = "MUSICGOAL" | < | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | # I wonder what that is for --------------------------------------- class musicgoal (ChannelPlugin): # desc module = "musicgoal" title = "MUSICGOAL" homepage = "http://www.musicgoal.com/" base_url = homepage listformat = "url/direct" # settings config = [ ] |
︙ | ︙ |
Modified channels/myoggradio.py from [68cf24bd7d] to [a4c03f3784].
1 2 | # # api: streamtuner2 | | | > > < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # # api: streamtuner2 # title: MyOggRadio # description: Open source internet radio directory. # type: channel # category: radio # version: 0.5 # priority: standard # depends: json, StringIO # # MyOggRadio is an open source radio station directory. Because this matches # well with streamtuner2, there's now a project partnership. Shared streams can easily # be downloaded in this channel plugin. And streamtuner2 users can easily share their # favourite stations into the MyOggRadio directory. # |
︙ | ︙ | |||
35 36 37 38 39 40 41 | class myoggradio(ChannelPlugin): # description title = "MyOggRadio" module = "myoggradio" homepage = "http://www.myoggradio.org/" api = "http://ehm.homelinux.org/MyOggRadio/" | < | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | class myoggradio(ChannelPlugin): # description title = "MyOggRadio" module = "myoggradio" homepage = "http://www.myoggradio.org/" api = "http://ehm.homelinux.org/MyOggRadio/" listformat = "url/direct" # config data config = [ {"name":"myoggradio_login", "type":"text", "value":"user:password", "description":"Account for storing personal favourites."}, {"name":"myoggradio_morph", "type":"boolean", "value":0, "description":"Convert pls/m3u into direct shoutcast url."}, ] |
︙ | ︙ |
Modified channels/punkcast.py from [57433ea58f] to [e751e37b9b].
1 2 | # api: streamtuner2 | | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # api: streamtuner2 # title: PunkCast # description: Online video site that covered NYC artists. Not updated anymore. # type: channel # category: video # version: 0.1 # priority: rare # # # Disables itself per default. # ST1 looked prettier with random images within. # |
︙ | ︙ | |||
34 35 36 37 38 39 40 | # basic.ch broadcast archive class punkcast (ChannelPlugin): # description title = "punkcast" module = "punkcast" homepage = "http://www.punkcast.com/" | < | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | # basic.ch broadcast archive class punkcast (ChannelPlugin): # description title = "punkcast" module = "punkcast" homepage = "http://www.punkcast.com/" # keeps category titles->urls catmap = {} categories = ["list"] default = "list" current = "list" |
︙ | ︙ |
Modified channels/shoutcast.py from [19bd20260e] to [834f2c6518].
1 2 | # # api: streamtuner2 | | | | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # # api: streamtuner2 # title: Shoutcast.com # description: Primary list of shoutcast servers (now managed by radionomy). # type: channel # category: radio # priority: default # version: 1.3 # depends: pq, re, http # author: Mario # original: Jean-Yves Lefort # # Shoutcast is a server software for audio streaming. It automatically spools # station information on shoutcast.com, which this plugin can read out. # # After its recent aquisition the layout got slimmed down considerably. So |
︙ | ︙ | |||
31 32 33 34 35 36 37 | # SHOUTcast data module ---------------------------------------- class shoutcast(channels.ChannelPlugin): # desc api = "streamtuner2" module = "shoutcast" title = "SHOUTcast" | < | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | # SHOUTcast data module ---------------------------------------- class shoutcast(channels.ChannelPlugin): # desc api = "streamtuner2" module = "shoutcast" title = "SHOUTcast" homepage = "http://www.shoutcast.com/" base_url = "http://shoutcast.com/" listformat = "audio/x-scpls" # settings config = [ ] |
︙ | ︙ |
Modified channels/timer.py from [73a61c99cb] to [57941064a8].
1 2 | # # api: streamtuner2 | | | > > < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # # api: streamtuner2 # title: Recording timer # description: Schedules play/record events for bookmarked radio stations. # type: feature # category: ui # depends: kronos # version: 0.5 # priority: optional # support: unsupported # # Okay, while programming this, I missed the broadcast I wanted to hear. Again(!) # But still this is a useful extension, as it allows recording and playing specific # stations at a programmed time and interval. It accepts a natural language time # string when registering a stream. (Via streams menu > extension > add timer) |
︙ | ︙ | |||
31 32 33 34 35 36 37 | # timed events (play/record) within bookmarks tab class timer: # plugin info module = "timer" title = "Timer" | < | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | # timed events (play/record) within bookmarks tab class timer: # plugin info module = "timer" title = "Timer" # configuration settings config = [ ] timefield = "playing" |
︙ | ︙ |
Modified channels/xiph.py from [4dfeffc128] to [b7c1ca97af].
1 2 3 | # # api: streamtuner2 # title: Xiph.org | | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # # api: streamtuner2 # title: Xiph.org # description: ICEcast radio directory. Now utilizes a cached JSON API. # type: channel # category: radio # version: 0.3 # priority: standard # # # Xiph.org maintains the Ogg streaming standard and Vorbis audio compression # format, amongst others. The ICEcast server is an alternative to SHOUTcast. # # It meanwhile provides a JSOL dump, which is faster to download and process. # So we'll use that over the older yp.xml. (Sadly it also doesn't output |
︙ | ︙ | |||
35 36 37 38 39 40 41 | # I wonder what that is for --------------------------------------- class xiph (ChannelPlugin): # desc api = "streamtuner2" module = "xiph" title = "Xiph.org" | < | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | # I wonder what that is for --------------------------------------- class xiph (ChannelPlugin): # desc api = "streamtuner2" module = "xiph" title = "Xiph.org" homepage = "http://dir.xiph.org/" #base_url = "http://api.dir.xiph.org/" json_url = "http://api.include-once.org/xiph/cache.php" listformat = "url/http" config = [ {"name":"xiph_min_bitrate", "value":64, "type":"int", "description":"minimum bitrate, filter anything below", "category":"filter"} ] |
︙ | ︙ |
Modified st2.py from [7776cafb92] to [6bfb3a77f9].
1 2 3 4 5 6 7 | #!/usr/bin/env python # encoding: UTF-8 # api: python # type: application # title: streamtuner2 # description: directory browser for internet radio / audio streams # depends: pygtk | pygi, threading, pyquery, kronos, requests | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/env python # encoding: UTF-8 # api: python # type: application # title: streamtuner2 # description: directory browser for internet radio / audio streams # depends: pygtk | pygi, threading, pyquery, kronos, requests # version: 2.1.1 # author: mario salzer # license: public domain # url: http://freshmeat.net/projects/streamtuner2 # config: <env name="http_proxy" value="" description="proxy for HTTP access" /> <env name="XDG_CONFIG_HOME" description="relocates user .config subdirectory" /> # category: multimedia # # |
︙ | ︙ | |||
74 75 76 77 78 79 80 | from processing import Process as Thread except: from threading import Thread Thread.stop = lambda self: None # add library path sys.path.insert(0, "/usr/share/streamtuner2") # pre-defined directory for modules | | > | 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 | from processing import Process as Thread except: from threading import Thread Thread.stop = lambda self: None # add library path sys.path.insert(0, "/usr/share/streamtuner2") # pre-defined directory for modules sys.path.append( "/usr/share/streamtuner2/bundle") # external libraries sys.path.insert(0, ".") # development module path # gtk modules from mygtk import pygtk, gtk, gobject, ui_file, mygtk, ver as GTK_VER # custom modules from config import conf # initializes itself, so all conf.vars are available right away from config import __print__, dbg import ahttp import action # needs workaround... (action.main=main) import channels from channels import * import favicon __version__ = "2.1.0" |
︙ | ︙ | |||
438 439 440 441 442 443 444 | mygtk.do(lambda:self.statusbar.push(sbar_cid, text)) pass # load plugins from /usr/share/streamtuner2/channels/ def load_plugin_channels(self): | | < < | < < < | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | mygtk.do(lambda:self.statusbar.push(sbar_cid, text)) pass # load plugins from /usr/share/streamtuner2/channels/ def load_plugin_channels(self): # find and order plugin files ls = channels.module_list() # step through for module in ls: gui_startup(2/10.0 + 7/10.0 * float(ls.index(module))/len(ls), "loading module "+module) # skip module if disabled if conf.plugins.get(module, 1) == False: |
︙ | ︙ | |||
749 750 751 752 753 754 755 | # aux win: settings UI class config_dialog (auxiliary_window): # display win_config, pre-fill text fields from global conf. object def open(self, widget): | > | < < | > > > | 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | # aux win: settings UI class config_dialog (auxiliary_window): # display win_config, pre-fill text fields from global conf. object def open(self, widget): if self.first_open: self.add_plugins() self.combobox_theme() self.first_open = 0 self.apply(conf.__dict__, "config_", 0) self.win_config.show() first_open = 1 def hide(self, *args): self.win_config.hide() return True |
︙ | ︙ | |||
814 815 816 817 818 819 820 | def apply_theme(self): if self.theme.get_active() >= 0: conf.theme = self.theme.get_model()[ self.theme.get_active()][0] main.load_theme() # add configuration setting definitions from plugins | < < < | < | > | < > > > > > > | | | | > > > | | | | | < < < | 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 | def apply_theme(self): if self.theme.get_active() >= 0: conf.theme = self.theme.get_model()[ self.theme.get_active()][0] main.load_theme() # add configuration setting definitions from plugins def add_plugins(self): for name,meta in channels.module_meta().items(): # add plugin load entry if name: cb = gtk.CheckButton(name) cb.child.set_markup("<b>%s</b> <i>(%s)</i> %s\n<small>%s</small>" % (meta["title"], meta["type"], meta.get("version", ""), meta["description"])) self.add_( "config_plugins_"+name, cb ) # look up individual plugin options, if loaded if self.channels.get(name) or self.features.get(name): c = self.channels.get(name) or self.features.get(name) for opt in c.config: # default values are already in conf[] dict (now done in conf.add_plugin_defaults) # display checkbox or text entry if opt["type"] == "boolean": cb = gtk.CheckButton(opt["description"]) #cb.set_line_wrap(True) self.add_( "config_"+opt["name"], cb ) else: self.add_( "config_"+opt["name"], gtk.Entry(), opt["description"] ) # spacer self.add_( "filler_pl_"+name, gtk.HSeparator() ) # put gtk widgets into config dialog notebook def add_(self, id, w, label=None, color=""): w.set_property("visible", True) main.widgets[id] = w if label: w.set_width_chars(10) w = self.hbox(w, self.label(label)) if color: w = mygtk.bg(w, color) self.plugin_options.pack_start(w) def label(self, label): label = gtk.Label(label) label.set_property("visible", True) label.set_line_wrap(True) label.set_size_request(250, -1) return label def hbox(self, w1, w2): vbox = gtk.HBox(homogeneous=False, spacing=10) vbox.set_property("visible", True) vbox.pack_start(w1, expand=False, fill=False) vbox.pack_start(w2, expand=True, fill=True) return vbox # save config def save(self, widget): self.apply(conf.__dict__, "config_", 1) self.apply_theme() conf.save(nice=1) |
︙ | ︙ |