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

⌈⌋ ⎇ branch:  streamtuner2


Check-in [d58eeed475]

Overview
Comment:Moved all config[] lists into plugin meta data fields (JSOL style retained). Add channel homepages as plugin url: field.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d58eeed475db3684431cab26179de261ffc5fedc
User & Date: mario on 2015-03-29 03:09:34
Other Links: manifest | tags
Context
2015-03-29
14:41
Less indentation, update pack: list. check-in: 3c07d74bb6 user: mario tags: trunk
03:09
Moved all config[] lists into plugin meta data fields (JSOL style retained). Add channel homepages as plugin url: field. check-in: d58eeed475 user: mario tags: trunk
03:08
Use .meta[title] instead of literal property. Channel list in config_dialog completed again with disabled plugins. New tooltop for comment doc section. check-in: ead195d25c user: mario tags: trunk
Changes

Modified channels/bookmarks.py from [4bb313d276] to [145c80c0b6].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# encoding: UTF-8
# api: streamtuner2
# title: bookmarks
# description: For collecting favourites. And provides some feature/category plugins.
# type: channel
# version: 1.5
# category: channel
# priority: core
# config: {"name":"like_my_bookmarks", "type":"boolean", "value":0, "description":"I like my bookmarks", color: "#f7e7d7"}
# 
# Favourite lists.
#
# This module lists static content from ~/.config/streamtuner2/bookmarks.json.
# Any bookmarked station will appear with a star ★ icon in other channels.
#
# Some feature extensions inject custom subcategories here. For example the








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# encoding: UTF-8
# api: streamtuner2
# title: bookmarks
# description: For collecting favourites. And provides some feature/category plugins.
# type: channel
# version: 1.5
# category: channel
# priority: core
# config: { name: like_my_bookmarks,  type: boolean, value: 0, description: "I like my bookmarks" }
# 
# Favourite lists.
#
# This module lists static content from ~/.config/streamtuner2/bookmarks.json.
# Any bookmarked station will appear with a star ★ icon in other channels.
#
# Some feature extensions inject custom subcategories here. For example the

Modified channels/dirble.py from [31ed68ff70] to [8298579c5d].

1
2
3
4
5
6
7



8

9
10
11
12
13
14
15
# encoding: UTF-8
# api: streamtuner2
# title: Dirble
# description: Open radio station directory.
# version: 0.2
# type: channel
# category: radio



# priority: optional

# documentation: http://dirble.com/developer/api
#
# Provides a nice JSON API, so is easy to support.
#
# However useful station information (homepage, etc.) only
# with extraneous requests. So just for testing as of now.
#







>
>
>

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# encoding: UTF-8
# api: streamtuner2
# title: Dirble
# description: Open radio station directory.
# version: 0.2
# type: channel
# category: radio
# config:
#    { name: dirble_api_key,  value: "",  type: text,  description: Custom API access key. },
#    { name: dirble_fetch_homepage,  value: 0,  type: boolean,  description: Also fetch homepages when updating stations. (Rather slow.) }
# priority: optional
# url: http://dirble.com/
# documentation: http://dirble.com/developer/api
#
# Provides a nice JSON API, so is easy to support.
#
# However useful station information (homepage, etc.) only
# with extraneous requests. So just for testing as of now.
#
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

# Surfmusik sharing site
class dirble (ChannelPlugin):

    # description
    title = "Dirble"
    module = "dirble"
    homepage = "http://dirble.com/"
    has_search = True
    listformat = "audio/x-scpls"
    titles = dict(listeners=False, playing="Location")

    categories = []
    config = [
        {"name": "dirble_api_key",
         "value": "",
         "type": "text",
         "description": "Custom API access key."
        },
        {"name": "dirble_fetch_homepage",
         "value": 0,
         "type": "boolean",
         "description": "Also fetch homepages when updating stations. (This is super slow, as it requires one extra request for each station.)"
        }
    ]    
    catmap = {}
    
    base = "http://api.dirble.com/v1/%s/apikey/%s/"
    cid = "a0bdd7b8efc2f5d1ebdf1728b65a07ece4c73de5"


    # Retrieve cat list and map







<





<
<
<
<
<
<
<
<
<
<
<
<







31
32
33
34
35
36
37

38
39
40
41
42












43
44
45
46
47
48
49

# Surfmusik sharing site
class dirble (ChannelPlugin):

    # description
    title = "Dirble"
    module = "dirble"

    has_search = True
    listformat = "audio/x-scpls"
    titles = dict(listeners=False, playing="Location")

    categories = []












    catmap = {}
    
    base = "http://api.dirble.com/v1/%s/apikey/%s/"
    cid = "a0bdd7b8efc2f5d1ebdf1728b65a07ece4c73de5"


    # Retrieve cat list and map

Modified channels/file.py from [4d4dd4f9cc] to [6ec2a8db67].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
# api: streamtuner2
# title: File browser
# description: Displays mp3/oggs or m3u/pls files from local media file directories.
# type: channel
# category: media
# version: 0.1
# priority: optional
# depends: mutagen
# config:  
#   {name:"file_browser_dir", "type":"text", "value": "~/Music, /media/music", "description":"list of directories to scan for audio files"},
#   {name:"file_browser_ext", "type":"text", "value":"mp3,ogg, m3u,pls,xspf, avi,flv,mpg,mp4", "description":"file type filter"},
#
#
# Local file browser.
#
#



# modules
import os
import re










|
|

<

<







1
2
3
4
5
6
7
8
9
10
11
12
13

14

15
16
17
18
19
20
21
#
# api: streamtuner2
# title: File browser
# description: Displays mp3/oggs or m3u/pls files from local media file directories.
# type: channel
# category: media
# version: 0.1
# priority: optional
# depends: mutagen
# config:  
#   { name: file_browser_dir, type: text, value: "~/Music, /media/music", description: "List of directories to scan for audio files." },
#   { name: file_browser_ext, type: text, value: "mp3,ogg, m3u,pls,xspf, avi,flv,mpg,mp4", description: "File type/extension filter." },
#

# Local file browser.

#



# modules
import os
import re

Modified channels/global_key.py from [8937954709] to [3e28ed6ce5].

1
2
3
4
5
6
7




8
9
10
11
12
13
14
#
# 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.







>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#
# api: streamtuner2
# title: Global keyboard shortcut
# description: Allows switching between bookmarked radios via key press.
# type: feature
# category: ui
# version: 0.2
# config:
#    { name="switch_key", type="text", value="XF86Forward", description="Global key shortcut for switching radio." },
#    { name="switch_channel", type="text", value="bookmarks:favourite", description="Station list and channels to alternate in." },
#    { name="switch_random", type="boolean", value=0, description="Pick random channel, instead of next." },
# 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.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# register a key
class global_key(object):

    module = "global_key"
    title = "keyboard shortcut"
    meta = plugin_meta()
    
    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


    # register
    def __init__(self, parent):
        self.parent = parent
        try:







<
<
<
<
<
<







30
31
32
33
34
35
36






37
38
39
40
41
42
43

# register a key
class global_key(object):

    module = "global_key"
    title = "keyboard shortcut"
    meta = plugin_meta()






    last = 0


    # register
    def __init__(self, parent):
        self.parent = parent
        try:

Modified channels/history.py from [07819073c4] to [dff5e057f5].

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
#
# api: streamtuner2
# title: History
# description: List recently played stations under favourites > history.
# version: 1.0
# type: category
# category: ui
# priority: optional
# config:  { name: history,  type: int,  value: 20,  description: Number of last played streams to keep in history list.,  category: limit }

#
# 
# Lists last activated streams in a new [history] tab in the favourites
# channel.
#
#
#



from config import *
from channels import *








|
|
>




<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
#
# api: streamtuner2
# title: History
# description: List recently played stations under favourites > history.
# version: 1.0
# type: category
# category: ui
# config:
#     { name: history,  type: int,  value: 20,  description: Number of last played streams to keep in history list.,  category: limit }
# priority: optional
#
# 
# Lists last activated streams in a new [history] tab in the favourites
# channel.


#



from config import *
from channels import *

Modified channels/icast.py from [0e4b7862b4] to [a070747868].

1
2
3
4
5
6

7
8

9
10
11
12
13
14
15
# encoding: UTF-8
# api: streamtuner2
# title: iCast
# description: Open collaborative stream directory
# version: 0.1
# type: channel

# category: radio
# priority: optional

# documentation: http://api.icast.io/
#
# A modern alternative to ShoutCast/ICEcast.
# Streams are user-contributed, but often lack meta data (homepage) and
# there's no ordering by listeneres/popularity.
#
# OTOH it's every easy to interface with. Though the repeated API queries


|



>


>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# encoding: UTF-8
# api: streamtuner2
# title: iCast.io
# description: Open collaborative stream directory
# version: 0.1
# type: channel
# url: http://www.icast.io/
# category: radio
# priority: optional
# config: -
# documentation: http://api.icast.io/
#
# A modern alternative to ShoutCast/ICEcast.
# Streams are user-contributed, but often lack meta data (homepage) and
# there's no ordering by listeneres/popularity.
#
# OTOH it's every easy to interface with. Though the repeated API queries
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    module = "icast"
    homepage = "http://www.icast.io/"
    has_search = True
    listformat = "audio/x-scpls"
    titles = dict(listeners=False, bitrate=False, playing=False)

    categories = []
    config = [
    ]    
    
    base = "http://api.icast.io/1/"
    

    # Categories require little post-processing, just dict into list conversion
    def update_categories(self):
        self.categories = []







<
<







35
36
37
38
39
40
41


42
43
44
45
46
47
48
    module = "icast"
    homepage = "http://www.icast.io/"
    has_search = True
    listformat = "audio/x-scpls"
    titles = dict(listeners=False, bitrate=False, playing=False)

    categories = []


    
    base = "http://api.icast.io/1/"
    

    # Categories require little post-processing, just dict into list conversion
    def update_categories(self):
        self.categories = []

Modified channels/internet_radio.py from [1c5b48beed] to [e1356b6b1d].

1
2
3
4
5
6
7



8
9
10
11
12
13
14
#
# api: streamtuner2
# title: Internet-Radio.com
# description: Broad list of webradios from all genres.
# type: channel
# category: radio
# version: 1.2



# priority: standard
#
# Internet-Radio.co.uk/.com is one of the largest directories of streams.
# Available music genre classifications are mirrored verbatim and flatly.
#
# The new version of this plugin alternates between PyQuery and Regex
# station extraction. Both overlook some paid or incomplete entries.


|




>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#
# api: streamtuner2
# title: Internet-Radio
# description: Broad list of webradios from all genres.
# type: channel
# category: radio
# version: 1.2
# url: http://www.internet-radio.org.uk/
# config:
#    { name: internetradio_max_pages,  type: int,  value: 5,  category: limit,  description: How many pages to fetch and read. }
# priority: standard
#
# Internet-Radio.co.uk/.com is one of the largest directories of streams.
# Available music genre classifications are mirrored verbatim and flatly.
#
# The new version of this plugin alternates between PyQuery and Regex
# station extraction. Both overlook some paid or incomplete entries.
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

    # description
    title = "InternetRadio"
    module = "internet_radio"
    homepage = "http://www.internet-radio.org.uk/"
    listformat = "audio/x-scpls"
    
    # settings
    config = [
        {
            "name": "internetradio_max_pages",
            "type": "int",
            "value": 5,
            "category": "limit",
            "description": "How many pages to fetch and read.",
        },
    ]
    

    # category map
    categories = []
    current = ""
    default = ""


    # load genres







<
<
<
<
<
<
<
<
<
<
<
<







40
41
42
43
44
45
46












47
48
49
50
51
52
53

    # description
    title = "InternetRadio"
    module = "internet_radio"
    homepage = "http://www.internet-radio.org.uk/"
    listformat = "audio/x-scpls"
    












    # category map
    categories = []
    current = ""
    default = ""


    # load genres

Modified channels/itunes.py from [e8f81d7822] to [c564d09eeb].

1
2
3
4
5
6
7

8

9
10
11
12
13
14
15
# encoding: UTF-8
# api: streamtuner2
# title: iTunes Radio (via RS)
# description: iTunes unsorted station list via RoliSoft Radio Playlist caching webservice.
# version: 0.1
# type: channel
# category: radio

# priority: optional

# documentation: http://lab.rolisoft.net/playlists.html
#
# Provides pre-parsed radio station playlists for various services
#  → Shoutcast
#  → Xiph/ICEcast
#  → Tunein
#  → iTunes


|




>

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# encoding: UTF-8
# api: streamtuner2
# title: iTunes Radio
# description: iTunes unsorted station list via RoliSoft Radio Playlist caching webservice.
# version: 0.1
# type: channel
# category: radio
# url: http://www.itunes.com?
# priority: optional
# config: -
# documentation: http://lab.rolisoft.net/playlists.html
#
# Provides pre-parsed radio station playlists for various services
#  → Shoutcast
#  → Xiph/ICEcast
#  → Tunein
#  → iTunes
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
        "RnB",
        "Sports Radio",
        "Top 40",
        "'70s Retro",
        "'80s Flashback",
        "'90s Hits",
    ]
    config = [
    ]    
    
    base = "http://lab.rolisoft.net/playlists/itunes.php"
    #base = "http://aws-eu.rolisoft.net/playlists/itunes.php"
    #base = "http://aws-us.rolisoft.net/playlists/itunes.php"
    

    # static list for iTunes







<
<







65
66
67
68
69
70
71


72
73
74
75
76
77
78
        "RnB",
        "Sports Radio",
        "Top 40",
        "'70s Retro",
        "'80s Flashback",
        "'90s Hits",
    ]


    
    base = "http://lab.rolisoft.net/playlists/itunes.php"
    #base = "http://aws-eu.rolisoft.net/playlists/itunes.php"
    #base = "http://aws-us.rolisoft.net/playlists/itunes.php"
    

    # static list for iTunes

Modified channels/jamendo.py from [fc2a3bf698] to [3aba6ea22f].

1
2
3
4
5
6
7

8
9
10
11


12
13
14
15
16
17
18
19

# api: streamtuner2
# title: Jamendo
# description: A license-free music collection and artist hub.
# type: channel
# version: 2.2
# category: radio

# depends: json
# priority: default
# config: 
#    { name: "jamendo_stream_format", type: "select", value: "ogg", select: "ogg=Ogg Vorbis|mp32=MP3, 192vbr|mp31=MP3, 96kbps|flac=Xiph FLAC", description: "Default streaming audio format. Albums and playlists still return Vorbis mostly for best quality." }


#
#
# 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.
#
# Tracks are queried by genre, where currently there's just a small built-in







>

<

|
>
>
|







1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21

# api: streamtuner2
# title: Jamendo
# description: A license-free music collection and artist hub.
# type: channel
# version: 2.2
# category: radio
# url: http://jamendo.com/
# depends: json

# config: 
#    { name: jamendo_stream_format, value: ogg,  type: select,  select: "ogg=Ogg Vorbis|mp32=MP3, 192vbr|mp31=MP3, 96kbps|flac=Xiph FLAC",  description: "Default streaming audio format. Albums and playlists still return Vorbis mostly for best quality." }
#    { name: jamendo_image_size,    value: 50,   type: select,  select: "25=25px|35=35px|50=50px|55=55px|60=60px|65=65px|70=70px|75=75px|85=85px|100=100px|130=130px|150=150px|200=200px|300=300px",  description: "Preview images size (height and width) for albums or tracks." }
#    { name: jamendo_count,         value: 1,    type:text,     description: "How many result sets (200 entries each) to retrieve." }
# 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.
#
# Tracks are queried by genre, where currently there's just a small built-in
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
    listformat = "url/http"
    api_base = "http://api.jamendo.com/v3.0/"
    cid = "49daa4f5"

    categories = []

    titles = dict( title="Title", playing="Album/Artist/User", bitrate=False, listeners=False )
 
    config = [
        {"name":"jamendo_stream_format",
         "value":"ogg",
         "type": "select",
         "select": "ogg=Ogg Vorbis|mp32=MP3, 192vbr|mp31=MP3, 96kbps|flac=Xiph FLAC",
         "description": "Default streaming audio format. Albums and playlists still return Vorbis mostly for best quality."
        },
        {"name": "jamendo_image_size",
         "value": "50",
         "type": "select",
         "select": "25=25px|35=35px|50=50px|55=55px|60=60px|65=65px|70=70px|75=75px|85=85px|100=100px|130=130px|150=150px|200=200px|300=300px",
         "description": "Preview images size (height and width) for albums or tracks."
        },
        {"name": "jamendo_count",
         "value": "1",     # "offset": in API is broken, so leave this at 1
         "type":"text",
         "description": "How many result sets (200 entries each) to retrieve."
        }
    ]    
    


    # refresh category list
    def update_categories(self):

        self.categories = [
            "radios",







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







63
64
65
66
67
68
69





















70
71
72
73
74
75
76
    listformat = "url/http"
    api_base = "http://api.jamendo.com/v3.0/"
    cid = "49daa4f5"

    categories = []

    titles = dict( title="Title", playing="Album/Artist/User", bitrate=False, listeners=False )























    # refresh category list
    def update_categories(self):

        self.categories = [
            "radios",

Modified channels/links.py from [4b9e35f7fc] to [574a0e1823].

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
#
# api: streamtuner2
# title: Links to directory services
# description: Static list of various music directory websites.
# type: category
# category: web
# version: 0.2
# priority: default
#
#
# Simply adds a "links" entry in bookmarks tab, where known channels
# and some others are listed with homepage links.
#
#


from config import *
from channels import *
import copy



# hooks into main.bookmarks
class links (object):

    # plugin info
    module = "links"
    title = "Links"
    version = 0.1
    meta = plugin_meta()
    
    
    # configuration settings
    config = [    ]
    
    # list
    streams = [    ]
    default = [
        ("stream", "rad.io", "http://www.rad.io/"),
        ("stream", "RadioTower", "http://www.radiotower.com/"),
        ("stream", "8tracks", "http://8tracks.com/"),
        ("stream", "TuneIn", "http://tunein.com/"),








|

|
|
<


















<
<
<
<







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
#
# api: streamtuner2
# title: Links to directory services
# description: Static list of various music directory websites.
# type: category
# category: web
# version: 0.2
# priority: default
# config: -
#
# Simply adds a "links" entry in bookmarks tab, where known services
# are listed with homepage links.

#


from config import *
from channels import *
import copy



# hooks into main.bookmarks
class links (object):

    # plugin info
    module = "links"
    title = "Links"
    version = 0.1
    meta = plugin_meta()
    




    # list
    streams = [    ]
    default = [
        ("stream", "rad.io", "http://www.rad.io/"),
        ("stream", "RadioTower", "http://www.radiotower.com/"),
        ("stream", "8tracks", "http://8tracks.com/"),
        ("stream", "TuneIn", "http://tunein.com/"),

Modified channels/live365.py from [e1bde0795c] to [2e2986e12a].

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

# api: streamtunter2
# title: Live365
# description: Around 5000 categorized internet radio streams, some paid ad-free ones.

# type: channel
# category: radio

# version: 0.3
# priority: optional
#
# 
#
# We're currently extracting from the JavaScript;
#
#    stn.set("param", "value");
#
# And using a HTML5 player direct URL now:
#
#    /cgi-bin/play.pls?stationid=%s&direct=1&file=%s.pls
#
#
#


# streamtuner2 modules
from config import conf
from mygtk import mygtk
import ahttp as http




>


>
|

<









<
<







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

# api: streamtunter2
# title: Live365
# description: Around 5000 categorized internet radio streams, some paid ad-free ones.
# version: 0.3
# type: channel
# category: radio
# url: http://www.live365.com/
# config: -
# priority: optional

# 
#
# We're currently extracting from the JavaScript;
#
#    stn.set("param", "value");
#
# And using a HTML5 player direct URL now:
#
#    /cgi-bin/play.pls?stationid=%s&direct=1&file=%s.pls


#


# streamtuner2 modules
from config import conf
from mygtk import mygtk
import ahttp as http

Modified channels/modarchive.py from [2d0aeb3385] to [681b28ed63].

1
2
3
4
5
6

7

8
9
10
11
12
13
14

# api: streamtuner2
# title: MODarchive
# description: Collection of module / tracker audio files (MOD, S3M, XM, etc.)
# type: channel
# version: 0.2

# priority: extra

# category: music
#
#
# 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.






>

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# api: streamtuner2
# title: MODarchive
# description: Collection of module / tracker audio files (MOD, S3M, XM, etc.)
# type: channel
# version: 0.2
# url: http://www.modarchive.org/
# priority: extra
# config: -
# category: music
#
#
# 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.

Modified channels/myoggradio.py from [7d2a0014e3] to [cdc167a1f7].

1
2
3
4
5
6
7
8
9




10
11
12
13
14
15
16
#
# 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.
#
# Beforehand an account needs to be configured in the settings. (Registration







|

>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#
# api: streamtuner2
# title: MyOggRadio
# description: Open source internet radio directory.
# type: channel
# category: radio
# version: 0.5
# url: http://www.myoggradio.org/
# depends: json, StringIO
# 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." }
# priority: standard
#
# 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.
#
# Beforehand an account needs to be configured in the settings. (Registration
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    # description
    title = "MyOggRadio"
    module = "myoggradio"
    homepage = "http://www.myoggradio.org/"
    api = "http://www.myoggradio.org/"
    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."},
    ]
    
    # hide unused columns
    titles = dict(playing=False, listeners=False, bitrate=False)
    

    # category map
    categories = ['common', 'personal']
    default = 'common'







<
<
<
<
<
<







42
43
44
45
46
47
48






49
50
51
52
53
54
55
    # description
    title = "MyOggRadio"
    module = "myoggradio"
    homepage = "http://www.myoggradio.org/"
    api = "http://www.myoggradio.org/"
    listformat = "url/direct"
    






    # hide unused columns
    titles = dict(playing=False, listeners=False, bitrate=False)
    

    # category map
    categories = ['common', 'personal']
    default = 'common'

Modified channels/punkcast.py from [31af6f440a] to [fca198bf93].

1
2
3
4
5
6
7


8
9
10
11
12
13
14

# 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.
#








>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# api: streamtuner2
# title: PunkCast
# description: Online video site that covered NYC artists. Not updated anymore.
# type: channel
# category: video
# version: 0.1
# url: http://www.punkcast.com/
# config: -
# priority: rare
#
#
# Disables itself per default.
# ST1 looked prettier with random images within.
#

Modified channels/radiotray.py from [589665392e] to [2fd23e85be].

1
2
3
4
5
6
7


8
9
10
11
12
13
14
# api: dbus
# title: RadioTray hook
# description: Allows to bookmark stations to RadioTray
# version: 0.2
# type: feature
# category: bookmarks
# depends: deb:python-dbus, deb:streamtuner2, deb:python-xdg


# priority: extra
# id: streamtuner2-radiotray
# pack: radiotray.py=/usr/share/streamtuner2/channels/
#
# Adds a context menu "Keep in RadioTray.." to bookmark streams
# in RadioTray.  Until a newer version exposes addRadio(), this
# plugin will fall back to just playUrl().







>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# api: dbus
# title: RadioTray hook
# description: Allows to bookmark stations to RadioTray
# version: 0.2
# type: feature
# category: bookmarks
# depends: deb:python-dbus, deb:streamtuner2, deb:python-xdg
# config: -
# url: http://radiotray.sourceforge.net/
# priority: extra
# id: streamtuner2-radiotray
# pack: radiotray.py=/usr/share/streamtuner2/channels/
#
# Adds a context menu "Keep in RadioTray.." to bookmark streams
# in RadioTray.  Until a newer version exposes addRadio(), this
# plugin will fall back to just playUrl().
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# not a channel plugin, just a category in bookmarks, and a context menu
class radiotray:

    # plugin info
    module = "radiotray"
    title = "RadioTray"
    meta = plugin_meta()
    # configuration settings
    config = [
    ]
    # bookmarks cat
    parent = None
    bm = None
    # radiotray config file / bookmarks
    rt_xml = "%s/%s/%s" % (xdg_data_home, "radiotray", "bookmarks.xml")









<
<
<







40
41
42
43
44
45
46



47
48
49
50
51
52
53
# not a channel plugin, just a category in bookmarks, and a context menu
class radiotray:

    # plugin info
    module = "radiotray"
    title = "RadioTray"
    meta = plugin_meta()



    # bookmarks cat
    parent = None
    bm = None
    # radiotray config file / bookmarks
    rt_xml = "%s/%s/%s" % (xdg_data_home, "radiotray", "bookmarks.xml")


Modified channels/shoutcast.py from [f799791802] to [1749bea8b8].

1
2
3
4
5
6

7
8



9
10
11
12
13
14
15
16
17
18
#
# api: streamtuner2
# title: Shoutcast.com
# description: Primary list of shoutcast servers (now managed by radionomy).
# type: channel
# category: radio

# priority: default
# version: 1.5



# 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
# It has been aquired by Radionomy in 2014, since then significant changes
# took place. The former YP got deprecated, now seemingly undeprecated.
#
#   http://wiki.winamp.com/wiki/SHOUTcast_Radio_Directory_API 






>
|

>
>
>

<
<







1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20
#
# api: streamtuner2
# title: Shoutcast.com
# description: Primary list of shoutcast servers (now managed by radionomy).
# type: channel
# category: radio
# author: Mario
# original: Jean-Yves Lefort
# version: 1.5
# url: http://www.shoutcast.com/
# config: -
# priority: default
# depends: pq, re, http


#
# Shoutcast is a server software for audio streaming. It automatically spools
# station information on shoutcast.com
# It has been aquired by Radionomy in 2014, since then significant changes
# took place. The former YP got deprecated, now seemingly undeprecated.
#
#   http://wiki.winamp.com/wiki/SHOUTcast_Radio_Directory_API 
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65



# 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 = [
    ]
    
    # categories
    categories = []
    catmap = {"Choral": 35, "Winter": 275, "JROCK": 306, "Motown": 237, "Political": 290, "Tango": 192, "Ska": 22, "Comedy": 283, "Decades": 212, "European": 143, "Reggaeton": 189, "Islamic": 307, "Freestyle": 114, "French": 145, "Western": 53, "Dancepunk": 6, "News": 287, "Xtreme": 23, "Bollywood": 138, "Celtic": 141, "Kids": 278, "Filipino": 144, "Hanukkah": 270, "Greek": 146, "Punk": 21, "Spiritual": 211, "Industrial": 14, "Baroque": 33, "Talk": 282, "JPOP": 227, "Scanner": 291, "Mediterranean": 154, "Swing": 174, "Themes": 89, "IDM": 75, "40s": 214, "Funk": 236, "Rap": 110, "House": 74, "Educational": 285, "Caribbean": 140, "Misc": 295, "30s": 213, "Anniversary": 266, "Sports": 293, "International": 134, "Tribute": 107, "Piano": 41, "Romantic": 42, "90s": 219, "Latin": 177, "Grunge": 10, "Dubstep": 312, "Government": 286, "Country": 44, "Salsa": 191, "Hardcore": 11, "Afrikaans": 309, "Downtempo": 69, "Merengue": 187, "Psychedelic": 260, "Female": 95, "Bop": 167, "Tribal": 80, "Metal": 195, "70s": 217, "Tejano": 193, "Exotica": 55, "Anime": 277, "BlogTalk": 296, "African": 135, "Patriotic": 101, "Blues": 24, "Turntablism": 119, "Chinese": 142, "Garage": 72, "Dance": 66, "Valentine": 273, "Barbershop": 222, "Alternative": 1, "Technology": 294, "Folk": 82, "Klezmer": 152, "Samba": 315, "Turkish": 305, "Trance": 79, "Dub": 245, "Rock": 250, "Polka": 59, "Modern": 39, "Lounge": 57, "Indian": 149, "Hindi": 148, "Brazilian": 139, "Eclectic": 93, "Korean": 153, "Creole": 316, "Dancehall": 244, "Surf": 264, "Reggae": 242, "Goth": 9, "Oldies": 226, "Zouk": 162, "Environmental": 207, "Techno": 78, "Adult": 90, "Rockabilly": 262, "Wedding": 274, "Russian": 157, "Sexy": 104, "Chill": 92, "Opera": 40, "Emo": 8, "Experimental": 94, "Showtunes": 280, "Breakbeat": 65, "Jungle": 76, "Soundtracks": 276, "LoFi": 15, "Metalcore": 202, "Bachata": 178, "Kwanzaa": 272, "Banda": 179, "Americana": 46, "Classical": 32, "German": 302, "Tamil": 160, "Bluegrass": 47, "Halloween": 269, "College": 300, "Ambient": 63, "Birthday": 267, "Meditation": 210, "Electronic": 61, "50s": 215, "Chamber": 34, "Heartache": 96, "Britpop": 3, "Soca": 158, "Grindcore": 199, "Reality": 103, "00s": 303, "Symphony": 43, "Pop": 220, "Ranchera": 188, "Electro": 71, "Christmas": 268, "Christian": 123, "Progressive": 77, "Jazz": 163, "Trippy": 108, "Instrumental": 97, "Tropicalia": 194, "Fusion": 170, "Healing": 209, "Glam": 255, "80s": 218, "KPOP": 308, "Worldbeat": 161, "Mixtapes": 117, "60s": 216, "Mariachi": 186, "Soul": 240, "Cumbia": 181, "Inspirational": 122, "Impressionist": 38, "Gospel": 129, "Disco": 68, "Arabic": 136, "Idols": 225, "Ragga": 247, "Demo": 67, "LGBT": 98, "Honeymoon": 271, "Japanese": 150, "Community": 284, "Weather": 317, "Asian": 137, "Hebrew": 151, "Flamenco": 314, "Shuffle": 105}
    current = ""
    default = "Alternative"
    empty = ""







<


<


<
<
<
<







44
45
46
47
48
49
50

51
52

53
54




55
56
57
58
59
60
61



# SHOUTcast data module                                          ----------------------------------------
class shoutcast(channels.ChannelPlugin):

    # desc

    module = "shoutcast"
    title = "SHOUTcast"

    base_url = "http://shoutcast.com/"
    listformat = "audio/x-scpls"




    
    # categories
    categories = []
    catmap = {"Choral": 35, "Winter": 275, "JROCK": 306, "Motown": 237, "Political": 290, "Tango": 192, "Ska": 22, "Comedy": 283, "Decades": 212, "European": 143, "Reggaeton": 189, "Islamic": 307, "Freestyle": 114, "French": 145, "Western": 53, "Dancepunk": 6, "News": 287, "Xtreme": 23, "Bollywood": 138, "Celtic": 141, "Kids": 278, "Filipino": 144, "Hanukkah": 270, "Greek": 146, "Punk": 21, "Spiritual": 211, "Industrial": 14, "Baroque": 33, "Talk": 282, "JPOP": 227, "Scanner": 291, "Mediterranean": 154, "Swing": 174, "Themes": 89, "IDM": 75, "40s": 214, "Funk": 236, "Rap": 110, "House": 74, "Educational": 285, "Caribbean": 140, "Misc": 295, "30s": 213, "Anniversary": 266, "Sports": 293, "International": 134, "Tribute": 107, "Piano": 41, "Romantic": 42, "90s": 219, "Latin": 177, "Grunge": 10, "Dubstep": 312, "Government": 286, "Country": 44, "Salsa": 191, "Hardcore": 11, "Afrikaans": 309, "Downtempo": 69, "Merengue": 187, "Psychedelic": 260, "Female": 95, "Bop": 167, "Tribal": 80, "Metal": 195, "70s": 217, "Tejano": 193, "Exotica": 55, "Anime": 277, "BlogTalk": 296, "African": 135, "Patriotic": 101, "Blues": 24, "Turntablism": 119, "Chinese": 142, "Garage": 72, "Dance": 66, "Valentine": 273, "Barbershop": 222, "Alternative": 1, "Technology": 294, "Folk": 82, "Klezmer": 152, "Samba": 315, "Turkish": 305, "Trance": 79, "Dub": 245, "Rock": 250, "Polka": 59, "Modern": 39, "Lounge": 57, "Indian": 149, "Hindi": 148, "Brazilian": 139, "Eclectic": 93, "Korean": 153, "Creole": 316, "Dancehall": 244, "Surf": 264, "Reggae": 242, "Goth": 9, "Oldies": 226, "Zouk": 162, "Environmental": 207, "Techno": 78, "Adult": 90, "Rockabilly": 262, "Wedding": 274, "Russian": 157, "Sexy": 104, "Chill": 92, "Opera": 40, "Emo": 8, "Experimental": 94, "Showtunes": 280, "Breakbeat": 65, "Jungle": 76, "Soundtracks": 276, "LoFi": 15, "Metalcore": 202, "Bachata": 178, "Kwanzaa": 272, "Banda": 179, "Americana": 46, "Classical": 32, "German": 302, "Tamil": 160, "Bluegrass": 47, "Halloween": 269, "College": 300, "Ambient": 63, "Birthday": 267, "Meditation": 210, "Electronic": 61, "50s": 215, "Chamber": 34, "Heartache": 96, "Britpop": 3, "Soca": 158, "Grindcore": 199, "Reality": 103, "00s": 303, "Symphony": 43, "Pop": 220, "Ranchera": 188, "Electro": 71, "Christmas": 268, "Christian": 123, "Progressive": 77, "Jazz": 163, "Trippy": 108, "Instrumental": 97, "Tropicalia": 194, "Fusion": 170, "Healing": 209, "Glam": 255, "80s": 218, "KPOP": 308, "Worldbeat": 161, "Mixtapes": 117, "60s": 216, "Mariachi": 186, "Soul": 240, "Cumbia": 181, "Inspirational": 122, "Impressionist": 38, "Gospel": 129, "Disco": 68, "Arabic": 136, "Idols": 225, "Ragga": 247, "Demo": 67, "LGBT": 98, "Honeymoon": 271, "Japanese": 150, "Community": 284, "Weather": 317, "Asian": 137, "Hebrew": 151, "Flamenco": 314, "Shuffle": 105}
    current = ""
    default = "Alternative"
    empty = ""

Modified channels/surfmusik.py from [f86a97dfce] to [947dba565f].

1
2
3
4

5
6
7
8


9
10
11
12
13
14
15
# encoding: UTF-8
# api: streamtuner2
# title: SurfMusik
# description: User collection of streams categorized by region and genre.

# version: 0.5
# type: channel
# category: radio
# author: gorgonz123


# source: http://forum.ubuntuusers.de/topic/streamtuner2-zwei-internet-radios-anhoeren-au/3/
# recognizes: max_streams
#
# This plugin comes in German (SurfMusik) and English (SurfMusic) variations.
# It provides a vast collection of international stations and genres.
# While it's not an open source project, most entries are user contributed.
#




>



|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# encoding: UTF-8
# api: streamtuner2
# title: SurfMusik
# description: User collection of streams categorized by region and genre.
# author: gorgonz123
# version: 0.5
# type: channel
# category: radio
# config:
#   { name: surfmusik_lang,  value: EN,  type: select,  select: "DE=German|EN=English",  description: "Switching to a new category title language requires reloading the category tree.",  category: language  }
# priority: default
# source: http://forum.ubuntuusers.de/topic/streamtuner2-zwei-internet-radios-anhoeren-au/3/
# recognizes: max_streams
#
# This plugin comes in German (SurfMusik) and English (SurfMusic) variations.
# It provides a vast collection of international stations and genres.
# While it's not an open source project, most entries are user contributed.
#
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
    base = {
       "DE": ("http://www.surfmusik.de/", "genre/", "land/"),
       "EN": ("http://www.surfmusic.de/", "format/", "country/"),
    }

    categories = []
    titles = dict( genre="Genre", title="Station", playing="Location", bitrate=False, listeners=False )
 
    config = [
        {
            "name": "surfmusik_lang",
            "value": "EN",
            "type": "select",
            "select":"DE=German|EN=English",
            "description": "Switching to a new category title language requires reloading the category tree.",
            "category": "language",
        }
    ]    
    
    
    # Set channel title
    def __init__(self, parent=None):
        self.title = ("SurfMusik", "SurfMusic")[conf.get("surfmusik_lang", "EN") == "EN"]
        ChannelPlugin.__init__(self, parent)









<
<
<
<
<
<
<
<
<
<
<
<







45
46
47
48
49
50
51












52
53
54
55
56
57
58
    base = {
       "DE": ("http://www.surfmusik.de/", "genre/", "land/"),
       "EN": ("http://www.surfmusic.de/", "format/", "country/"),
    }

    categories = []
    titles = dict( genre="Genre", title="Station", playing="Location", bitrate=False, listeners=False )












    
    # Set channel title
    def __init__(self, parent=None):
        self.title = ("SurfMusik", "SurfMusic")[conf.get("surfmusik_lang", "EN") == "EN"]
        ChannelPlugin.__init__(self, parent)


Modified channels/timer.py from [2de8202f62] to [446fecc94b].

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
#
# 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)
#
# Programmed events are visible in "timer" under the "bookmarks" channel. Times
# are stored in the description field, and can thus be edited. However, after editing
# times manually, streamtuner2 must be restarted for the changes to take effect.
#


from config import *
from channels import *
import kronos
from mygtk import mygtk
from action import action
import copy
import re



# timed events (play/record) within bookmarks tab
class timer:

    # plugin info
    module = "timer"
    title = "Timer"
    meta = plugin_meta()
    
    
    # configuration settings
    config = [
    ]
    timefield = "playing"
    
    
    # kronos scheduler list
    sched = None
    
    








>
















|

















<
<







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
#
# api: streamtuner2
# title: Recording timer
# description: Schedules play/record events for bookmarked radio stations.
# type: feature
# category: ui
# depends: kronos
# version: 0.5
# config: -
# 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)
#
# Programmed events are visible in "timer" under the "bookmarks" channel. Times
# are stored in the description field, and can thus be edited. However, after editing
# times manually, streamtuner2 must be restarted for the changes to take effect.
#


from config import *
from channels import *
import kronos  # Doesn't work with Python3
from mygtk import mygtk
from action import action
import copy
import re



# timed events (play/record) within bookmarks tab
class timer:

    # plugin info
    module = "timer"
    title = "Timer"
    meta = plugin_meta()
    
    
    # configuration settings


    timefield = "playing"
    
    
    # kronos scheduler list
    sched = None
    
    

Modified channels/tunein.py from [8bcfe1b146] to [ac164614d0].

1
2
3
4
5
6
7


8
9
10
11
12
13
14
# encoding: UTF-8
# api: streamtuner2
# title: TuneIn
# description: Online Radio, Broadcasts, Podcasts
# version: 0.1
# type: channel
# category: radio


# priority: optional
# documentation: http://opml.radiotime.com/
#
# Utilized OPML for station/podcast entries.
#
# Only radio listings are queried for now. But there are
# heaps more talk and local show entries, etc. (Would require







>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# encoding: UTF-8
# api: streamtuner2
# title: TuneIn
# description: Online Radio, Broadcasts, Podcasts
# version: 0.1
# type: channel
# category: radio
# url: http://tunein.com/
# config: -
# priority: optional
# documentation: http://opml.radiotime.com/
#
# Utilized OPML for station/podcast entries.
#
# Only radio listings are queried for now. But there are
# heaps more talk and local show entries, etc. (Would require
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# TuneIn radio directory
class tunein (ChannelPlugin):

    # description
    title = "TuneIn"
    module = "tunein"
    homepage = "http://tunein.com/"
    has_search = True
    listformat = "audio/x-scpls"
    titles = dict(listeners=False)
    base = "http://opml.radiotime.com/"

    categories = ["local", "60's", "70's", "80's", "90's", "Adult Contemporary", "Alternative Rock", "Ambient", "Bluegrass", "Blues", "Bollywood", "Children's Music", "Christmas", "Classic Hits", "Classic Rock", "Classical", "College Radio", "Country", "Decades", "Disco", "Easy Listening", "Eclectic", "Electronic", "Folk", "Hip Hop", "Indie", "Internet Only", "Jazz", "Live Music", "Oldies", "Polka", "Reggae", "Reggaeton", "Religious", "Rock", "Salsa", "Soul and R&B", "Spanish Music", "Specialty", "Tango", "Top 40/Pop", "World"]
    config = []
    catmap = {"60's": "g407", "Live Music": "g2778", "Children's Music": "c530749", "Polka": "g84", "Tango": "g3149", "Top 40/Pop": "c57943", "90's": "g2677", "Eclectic": "g78", "Decades": "c481372", "Christmas": "g375", "Reggae": "g85", "Reggaeton": "g2771", "Oldies": "c57947", "Jazz": "c57944", "Specialty": "c418831", "Hip Hop": "c57942", "College Radio": "c100000047", "Salsa": "g124", "Bollywood": "g2762", "70's": "g92", "Country": "c57940", "Classic Hits": "g2755", "Internet Only": "c417833", "Disco": "g385", "Rock": "c57951", "Soul and R&B": "c1367173", "Blues": "g106", "Classic Rock": "g54", "Alternative Rock": "c57936", "Adult Contemporary": "c57935", "Classical": "c57939", "World": "c57954", "Indie": "g2748", "Religious": "c57950", "Bluegrass": "g63", "Spanish Music": "c57945", "Easy Listening": "c10635888", "Ambient": "g2804", "80's": "g42", "Electronic": "c57941", "Folk": "g79"}


    # Retrieve cat list and map
    def update_categories(self):
        self.categories = ["local"]
        self.catmap = {}







|





<







33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
# TuneIn radio directory
class tunein (ChannelPlugin):

    # description
    title = "TuneIn"
    module = "tunein"
    homepage = "http://tunein.com/"
    has_search = False
    listformat = "audio/x-scpls"
    titles = dict(listeners=False)
    base = "http://opml.radiotime.com/"

    categories = ["local", "60's", "70's", "80's", "90's", "Adult Contemporary", "Alternative Rock", "Ambient", "Bluegrass", "Blues", "Bollywood", "Children's Music", "Christmas", "Classic Hits", "Classic Rock", "Classical", "College Radio", "Country", "Decades", "Disco", "Easy Listening", "Eclectic", "Electronic", "Folk", "Hip Hop", "Indie", "Internet Only", "Jazz", "Live Music", "Oldies", "Polka", "Reggae", "Reggaeton", "Religious", "Rock", "Salsa", "Soul and R&B", "Spanish Music", "Specialty", "Tango", "Top 40/Pop", "World"]

    catmap = {"60's": "g407", "Live Music": "g2778", "Children's Music": "c530749", "Polka": "g84", "Tango": "g3149", "Top 40/Pop": "c57943", "90's": "g2677", "Eclectic": "g78", "Decades": "c481372", "Christmas": "g375", "Reggae": "g85", "Reggaeton": "g2771", "Oldies": "c57947", "Jazz": "c57944", "Specialty": "c418831", "Hip Hop": "c57942", "College Radio": "c100000047", "Salsa": "g124", "Bollywood": "g2762", "70's": "g92", "Country": "c57940", "Classic Hits": "g2755", "Internet Only": "c417833", "Disco": "g385", "Rock": "c57951", "Soul and R&B": "c1367173", "Blues": "g106", "Classic Rock": "g54", "Alternative Rock": "c57936", "Adult Contemporary": "c57935", "Classical": "c57939", "World": "c57954", "Indie": "g2748", "Religious": "c57950", "Bluegrass": "g63", "Spanish Music": "c57945", "Easy Listening": "c10635888", "Ambient": "g2804", "80's": "g42", "Electronic": "c57941", "Folk": "g79"}


    # Retrieve cat list and map
    def update_categories(self):
        self.categories = ["local"]
        self.catmap = {}

Modified channels/xiph.py from [a46d943cfe] to [f757c3da36].

1
2
3
4
5


6
7

8
9
10
11
12
13
14
# encoding: UTF-8
# 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





>
>

|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# encoding: UTF-8
# api: streamtuner2
# title: Xiph.org
# description: ICEcast radio directory. Now utilizes a cached JSON API.
# type: channel
# url: http://dir.xiph.org/
# version: 0.3
# category: radio
# config: 
#    { name: xiph_min_bitrate,  value: 64,  type: int,  description: "minimum bitrate, filter anything below",  category: filter }
# 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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
        api = "streamtuner2"
        module = "xiph"
        title = "Xiph.org"
        homepage = "http://dir.xiph.org/"
        #xml_url = "http://dir.xiph.org/yp.xml"
        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"}
        ]
        has_search = True

        # content
        categories = [ "pop", "top40" ]
        current = ""
        default = "pop"
        empty = None







<
<
<







53
54
55
56
57
58
59



60
61
62
63
64
65
66
        api = "streamtuner2"
        module = "xiph"
        title = "Xiph.org"
        homepage = "http://dir.xiph.org/"
        #xml_url = "http://dir.xiph.org/yp.xml"
        json_url = "http://api.include-once.org/xiph/cache.php"
        listformat = "url/http"



        has_search = True

        # content
        categories = [ "pop", "top40" ]
        current = ""
        default = "pop"
        empty = None

Modified channels/youtube.py from [a4a5b848e0] to [73f9e85160].

1
2
3
4
5
6

7




8
9
10
11
12
13
14
15
16
# encoding: UTF-8
# api: streamtuner2
# title: Youtube
# description: Channel, playlist and video browsing for youtube.
# type: channel
# version: 0.2

# category: video




# priority: optional
# suggests: youtube-dl
# 
# 
# Lists recently popular youtube videos by category or channels.
#
# Introduces the faux MIME type "video/youtube" for player and recording
# configuration; both utilizing `youtube-dl`. But VLC can consume Youtube
# URLs directly anyhow.






>

>
>
>
>

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# encoding: UTF-8
# api: streamtuner2
# title: Youtube
# description: Channel, playlist and video browsing for youtube.
# type: channel
# version: 0.2
# url: http://www.youtube.com/
# category: video
# config:
#    { name: youtube_channels,  type: text,  value: "Key Of Awesome, Pentatonix",  description: "Preferred channels to list videos from.",  category: select }
#    { name: youtube_region,  type: select,  select: "=No Region|AR=Argentina|AU=Australia|AT=Austria|BE=Belgium|BR=Brazil|CA=Canada|CL=Chile|CO=Colombia|CZ=Czech Republic|EG=Egypt|FR=France|DE=Germany|GB=Great Britain|HK=Hong Kong|HU=Hungary|IN=India|IE=Ireland|IL=Israel|IT=Italy|JP=Japan|JO=Jordan|MY=Malaysia|MX=Mexico|MA=Morocco|NL=Netherlands|NZ=New Zealand|PE=Peru|PH=Philippines|PL=Poland|RU=Russia|SA=Saudi Arabia|SG=Singapore|ZA=South Africa|KR=South Korea|ES=Spain|SE=Sweden|CH=Switzerland|TW=Taiwan|AE=United Arab Emirates|US=United States",  value: UK,  description: "Filter by region id.,  category: auth }
#    { name: youtube_wadsworth,  type: boolean,  value: 0,  description: "Apply Wadsworth constant.",  category: filter }
# priority: optional
# depends: bin:youtube-dl
# 
# 
# Lists recently popular youtube videos by category or channels.
#
# Introduces the faux MIME type "video/youtube" for player and recording
# configuration; both utilizing `youtube-dl`. But VLC can consume Youtube
# URLs directly anyhow.
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
        ["Music", "Comedy", "Movies", "Shows", "Trailers", "Film & Animation", "Entertainment", "News & Politics"],
        "topics",
        ["Pop", "Billboard charts", "Rock", "Hip Hop", "Classical", "Soundtrack", "Ambient",
         "Jazz", "Blues", "Soul", "Country", "Disco", "Dance", "House", "Trance", "Techno", "Electronica"],
        "my channels",
        ["Key of Awesome", "Pentatonix"]
    ] 

    # plugin settings 
    config = [
       {
          "name": "youtube_channels",
          "type": "text",
          "value": "Key Of Awesome, Pentatonix",
          "description": "Preferred channels to list videos from.",
          "category": "select",
       },
       {
          "name": "youtube_region",
          "type": "select",
          "select": "=No Region|AR=Argentina|AU=Australia|AT=Austria|BE=Belgium|BR=Brazil|CA=Canada|CL=Chile|CO=Colombia|CZ=Czech Republic|EG=Egypt|FR=France|DE=Germany|GB=Great Britain|HK=Hong Kong|HU=Hungary|IN=India|IE=Ireland|IL=Israel|IT=Italy|JP=Japan|JO=Jordan|MY=Malaysia|MX=Mexico|MA=Morocco|NL=Netherlands|NZ=New Zealand|PE=Peru|PH=Philippines|PL=Poland|RU=Russia|SA=Saudi Arabia|SG=Singapore|ZA=South Africa|KR=South Korea|ES=Spain|SE=Sweden|CH=Switzerland|TW=Taiwan|AE=United Arab Emirates|US=United States",
          "value": "UK",
          "description": "Filter by region id.",
          "category": "auth",
       },
       {
          "name": "youtube_wadsworth",
          "type": "boolean",
          "value": 0,
          "description": "Apply Wadsworth constant.",
          "category": "filter",
       },
    ]    

    # from GET https://www.googleapis.com/youtube/v3/videoCategories?part=id%2Csnippet&
    videocat_id = {
        "Film & Animation": 1,
        "Autos & Vehicles": 2,
        "Music": 10,
        "Pets & Animals": 15,
        "Sports": 17,







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







95
96
97
98
99
100
101



























102
103
104
105
106
107
108
        ["Music", "Comedy", "Movies", "Shows", "Trailers", "Film & Animation", "Entertainment", "News & Politics"],
        "topics",
        ["Pop", "Billboard charts", "Rock", "Hip Hop", "Classical", "Soundtrack", "Ambient",
         "Jazz", "Blues", "Soul", "Country", "Disco", "Dance", "House", "Trance", "Techno", "Electronica"],
        "my channels",
        ["Key of Awesome", "Pentatonix"]
    ] 



























    # from GET https://www.googleapis.com/youtube/v3/videoCategories?part=id%2Csnippet&
    videocat_id = {
        "Film & Animation": 1,
        "Autos & Vehicles": 2,
        "Music": 10,
        "Pets & Animals": 15,
        "Sports": 17,