Skip to content

Commit cdcffea

Browse files
[plugin.audio.radiobrowser] 2.0.0
1 parent 6b9dd15 commit cdcffea

10 files changed

Lines changed: 1182 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# directories
2+
dist
3+
4+
# files
5+
kodi-radio-browser.zip

plugin.audio.radiobrowser/LICENSE.txt

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# radio-browser.info add-on for kodi
2+
3+
This add-on provides your kodi with all radio stations, which are listed on [https://www.radio-browser.info/](https://www.radio-browser.info/).
4+
5+
## Develop this add-on
6+
7+
1. Install Kodi on your device.
8+
9+
2. Clone this repository into your `~/.kodi/addons` directory.
10+
11+
```bash
12+
git clone https://github.com/lookslikematrix/plugin.audio.radiobrowser
13+
ln -s $PWD/plugin.audio.radiobrowser ~/.kodi/addons/plugin.audio.radiobrowser
14+
```
15+
16+
3. Start Kodi
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<addon id="plugin.audio.radiobrowser" name="radio-browser.info" version="2.0.0" provider-name="lookslikematrix.de">
3+
<requires>
4+
<import addon="xbmc.python" version="3.0.0"/>
5+
<import addon="script.module.requests" version="2.31.0" />
6+
</requires>
7+
<extension point="xbmc.python.pluginsource" library="main.py">
8+
<provides>audio</provides>
9+
</extension>
10+
<extension point="xbmc.addon.metadata">
11+
<platform>all</platform>
12+
<summary lang="en">Radio-Browser</summary>
13+
<summary lang="bg">Radio-Browser</summary>
14+
<summary lang="de">Radio-Browser</summary>
15+
<description lang="en">Directory of radio stations that uses www.radio-browser.info as source.
16+
17+
If you miss your favourite station, just go to www.radio-browser.info and add it yourself. It is a wiki like system.</description>
18+
<description lang="bg">Колекция от радио станции, с източник www.radio-browser.info
19+
20+
Ако любимата ви станция не е в списъка, можете да я добавите като посетите www.radio-browser.info</description>
21+
<description lang="de">Verzeichnis von Radio-Stationen das www.radio-browser.info als Quelle nutzt.
22+
23+
Vermisst du deine Lieblingsstation? Kein problem: geh auf www.radio-browser.info und füge sie für alle Benutzer hinzu!</description>
24+
<license>GNU General Public License, Version 3</license>
25+
<website>https://www.radio-browser.info</website>
26+
<source>https://github.com/lookslikematrix/plugin.audio.radiobrowser</source>
27+
<news>
28+
2.0.0
29+
- Update add-on for Kodi &gt;= 20
30+
- Refactor add-on
31+
</news>
32+
<email>christian.decker@lookslikematrix.de</email>
33+
<assets>
34+
<icon>resources/icon.png</icon>
35+
<fanart>resources/fanart.jpg</fanart>
36+
</assets>
37+
</extension>
38+
</addon>

plugin.audio.radiobrowser/main.py

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
from json import dump, load
2+
from urllib import parse
3+
import sys
4+
5+
import xbmc
6+
import xbmcaddon
7+
import xbmcgui
8+
import xbmcplugin
9+
import xbmcvfs
10+
11+
import requests
12+
13+
14+
def get_text(id):
15+
addon = xbmcaddon.Addon(id=PLUGIN_ID)
16+
return addon.getLocalizedString(id).encode('utf-8')
17+
18+
def build_url(base_url, query):
19+
return f"{base_url}?{parse.urlencode(query)}"
20+
21+
def get_argument(arguments, text):
22+
argument = arguments.get(text, None)
23+
if argument:
24+
argument = argument[0]
25+
return argument
26+
27+
def add_directory(base_url, addon_handle, name: str, attributes: dict):
28+
localUrl = build_url(
29+
base_url,
30+
attributes
31+
)
32+
list_item = xbmcgui.ListItem(name)
33+
list_item.setArt(
34+
{
35+
"icon": "DefaultFolder.png"
36+
}
37+
)
38+
xbmcplugin.addDirectoryItem(handle=addon_handle, url=localUrl, listitem=list_item, isFolder=True)
39+
40+
def add_index_item(base_url, addon_handle, text_id: int, route: str):
41+
attributes = {
42+
"route": route
43+
}
44+
add_directory(base_url, addon_handle, get_text(text_id), attributes)
45+
46+
def add_station_item(base_url, addon_handle, route, station, is_my_station: bool = False):
47+
name = station["name"]
48+
favicon = station["favicon"]
49+
bitrate = station["bitrate"]
50+
stationuuid = station["stationuuid"]
51+
localUrl = build_url(
52+
base_url,
53+
{
54+
"route": route,
55+
"stationuuid": stationuuid
56+
}
57+
)
58+
list_item = xbmcgui.ListItem(name)
59+
list_item.setArt(
60+
{
61+
"icon": favicon,
62+
"thumb": favicon
63+
}
64+
)
65+
list_item.setProperty('IsPlayable', 'true')
66+
list_item.setInfo(
67+
type="music",
68+
infoLabels={
69+
"size":bitrate
70+
}
71+
)
72+
music_info = list_item.getMusicInfoTag()
73+
music_info.setTitle(name)
74+
75+
if not is_my_station:
76+
contextUrl = build_url(
77+
base_url,
78+
{
79+
"route": "add_station",
80+
"stationuuid": stationuuid
81+
}
82+
)
83+
list_item.addContextMenuItems([(get_text(32010), 'RunPlugin(%s)'%(contextUrl))])
84+
else:
85+
contextUrl = build_url(
86+
base_url,
87+
{
88+
"route": "remove_station",
89+
"stationuuid": stationuuid
90+
}
91+
)
92+
list_item.addContextMenuItems([(get_text(32009), 'RunPlugin(%s)'%(contextUrl))])
93+
94+
xbmcplugin.addDirectoryItem(handle=addon_handle, url=localUrl, listitem=list_item, isFolder=False)
95+
96+
def add_stations(endpoint):
97+
stations = request_radio_browser_api(endpoint)
98+
for station in stations:
99+
add_station_item(base_url, addon_handle, "play",station)
100+
101+
xbmcplugin.endOfDirectory(addon_handle)
102+
103+
104+
def index(base_url, addon_handle):
105+
add_index_item(base_url, addon_handle, 32008, "mystations")
106+
add_index_item(base_url, addon_handle, 32007, "search")
107+
add_index_item(base_url, addon_handle, 32000, "topclick")
108+
add_index_item(base_url, addon_handle, 32001, "topvote")
109+
add_index_item(base_url, addon_handle, 32002, "lastchange")
110+
add_index_item(base_url, addon_handle, 32003, "lastclick")
111+
add_index_item(base_url, addon_handle, 32004, "tags")
112+
add_index_item(base_url, addon_handle, 32005, "countries")
113+
xbmcplugin.endOfDirectory(addon_handle)
114+
115+
def request_radio_browser_api(endpoint):
116+
radio_browser_url = "https://all.api.radio-browser.info"
117+
request = f"{radio_browser_url}{endpoint}"
118+
xbmc.log(f"[ {request} ] Request URL")
119+
response = requests.get(request)
120+
response.raise_for_status()
121+
return response.json()
122+
123+
124+
def load_my_stations():
125+
my_stations = {}
126+
if not xbmcvfs.exists(PROFILE):
127+
xbmcvfs.mkdir(PROFILE)
128+
129+
if xbmcvfs.exists(MY_STATIONS_PATHS):
130+
with xbmcvfs.File(MY_STATIONS_PATHS, "r") as my_stations_file:
131+
my_stations = load(my_stations_file)
132+
133+
if "stations" not in my_stations:
134+
my_stations["stations"] = []
135+
return my_stations
136+
137+
def router(base_url, addon_handle, arguments):
138+
route = get_argument(arguments, "route")
139+
140+
if route == "mystations":
141+
my_stations = load_my_stations()
142+
for station in my_stations["stations"]:
143+
station = request_radio_browser_api(f"/json/stations/byuuid/{station}")[0]
144+
add_station_item(base_url, addon_handle, "play", station, is_my_station = True)
145+
146+
xbmcplugin.endOfDirectory(addon_handle)
147+
return
148+
149+
if route == "add_station":
150+
stationuuid = get_argument(arguments, "stationuuid")
151+
my_stations = load_my_stations()
152+
if stationuuid not in my_stations["stations"]:
153+
my_stations["stations"].append(stationuuid)
154+
155+
with xbmcvfs.File(MY_STATIONS_PATHS, "w") as my_stations_file:
156+
dump(my_stations, my_stations_file)
157+
158+
return
159+
160+
if route == "remove_station":
161+
stationuuid = get_argument(arguments, "stationuuid")
162+
my_stations = load_my_stations()
163+
my_stations["stations"].remove(stationuuid)
164+
165+
with xbmcvfs.File(MY_STATIONS_PATHS, "w") as my_stations_file:
166+
dump(my_stations, my_stations_file)
167+
168+
xbmc.executebuiltin("Container.Refresh")
169+
return
170+
171+
if route == "search":
172+
dialog = xbmcgui.Dialog()
173+
search_query = dialog.input(get_text(32011), type=xbmcgui.INPUT_ALPHANUM)
174+
add_stations(f"/json/stations/byname/{search_query}?order=clickcount&reverse=true&hidebroken=true")
175+
return
176+
177+
if route == "topclick":
178+
add_stations("/json/stations/topclick/100")
179+
return
180+
181+
if route == "topvote":
182+
add_stations("/json/stations/topvote/100")
183+
return
184+
185+
if route == "lastchange":
186+
add_stations("/json/stations/lastchange/100")
187+
return
188+
189+
if route == "lastclick":
190+
add_stations("/json/stations/lastclick/100")
191+
return
192+
193+
if route == "tag":
194+
tag = get_argument(arguments, "tag")
195+
add_stations(f"/json/stations/search?tag={tag}&tagExact=true&order=clickcount&reverse=true&hidebroken=true")
196+
return
197+
198+
if route == "country":
199+
countrycode = get_argument(arguments, "countrycode")
200+
add_stations(f"/json/stations/search?countrycode={countrycode}&order=clickcount&reverse=true&hidebroken=true")
201+
return
202+
203+
if route == "play":
204+
stationuuid = get_argument(arguments, "stationuuid")
205+
station = request_radio_browser_api(f"/json/stations/byuuid/{stationuuid}")[0]
206+
list_item = xbmcgui.ListItem(path=station["url"])
207+
list_item.setArt(
208+
{
209+
"thumb": station["favicon"]
210+
}
211+
)
212+
xbmcplugin.setResolvedUrl(addon_handle, True, list_item)
213+
return
214+
215+
if route == "tags":
216+
tags = request_radio_browser_api("/json/tags")
217+
218+
for tag in tags:
219+
attributes = {
220+
"route": "tag",
221+
"tag": tag["name"]
222+
}
223+
add_directory(base_url, addon_handle, tag["name"], attributes)
224+
225+
xbmcplugin.endOfDirectory(addon_handle)
226+
return
227+
228+
if route == "countries":
229+
countries = request_radio_browser_api("/json/countries")
230+
231+
for country in countries:
232+
attributes = {
233+
"route": "country",
234+
"countrycode": country["iso_3166_1"]
235+
}
236+
add_directory(base_url, addon_handle, country["name"], attributes)
237+
238+
xbmcplugin.endOfDirectory(addon_handle)
239+
return
240+
241+
index(base_url, addon_handle)
242+
return
243+
244+
if __name__ == "__main__":
245+
PLUGIN_ID = "plugin.audio.radiobrowser"
246+
PROFILE = f"special://profile/addon_data/{PLUGIN_ID}"
247+
MY_STATIONS_PATHS = f"{PROFILE}/mystations.json"
248+
base_url = sys.argv[0]
249+
addon_handle = int(sys.argv[1])
250+
xbmcplugin.setContent(addon_handle, 'songs')
251+
arguments = parse.parse_qs(sys.argv[2][1:])
252+
253+
router(base_url, addon_handle, arguments)
40 KB
Loading
59.4 KB
Loading
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Kodi Media Center language file
2+
# Addon Name: Radio Browser
3+
# Addon id: plugin.audio.radiobrowser
4+
# Addon Provider: segler_alex
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: XBMC Addons\n"
8+
"Report-Msgid-Bugs-To: segler_alex@web.de\n"
9+
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
10+
"PO-Revision-Date: 2016-06-25 19:27+0300\n"
11+
"Last-Translator: NEOhidra <neohidra@gmail.com>\n"
12+
"Language-Team: https://www.transifex.com/teamxbmc/xbmc-addons/language/bg/ <xbmc-bg@freelists.org>\n"
13+
"MIME-Version: 1.0\n"
14+
"Content-Type: text/plain; charset=UTF-8\n"
15+
"Content-Transfer-Encoding: 8bit\n"
16+
"Language: bg\n"
17+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
18+
"X-Generator: Poedit 1.8.7\n"
19+
20+
msgctxt "#32000"
21+
msgid "Top 100 clicked stations"
22+
msgstr "100-те най-посещавани"
23+
24+
msgctxt "#32001"
25+
msgid "Top 100 voted stations"
26+
msgstr "100-те с най-висок рейтинг"
27+
28+
msgctxt "#32002"
29+
msgid "Last 100 changed stations"
30+
msgstr "Последните 100 променени"
31+
32+
msgctxt "#32003"
33+
msgid "Last 100 clicked stations"
34+
msgstr "Последните 100 посетени"
35+
36+
msgctxt "#32004"
37+
msgid "Tags"
38+
msgstr "Етикети"
39+
40+
msgctxt "#32005"
41+
msgid "Countries"
42+
msgstr "Държави"
43+
44+
msgctxt "#32006"
45+
msgid "All"
46+
msgstr "Всички"
47+
48+
msgctxt "#32007"
49+
msgid "Search..."
50+
msgstr "Търсене..."
51+
52+
msgctxt "#32008"
53+
msgid "My Stations"
54+
msgstr "Моите станции"
55+
56+
msgctxt "#32009"
57+
msgid "Remove Station"
58+
msgstr "Премахване на станцията"
59+
60+
msgctxt "#32010"
61+
msgid "Add Station"
62+
msgstr "Добавете станция"
63+
64+
msgctxt "#32011"
65+
msgid "Search Station"
66+
msgstr "Търсене на станции"

0 commit comments

Comments
 (0)