diff --git a/src/lua-factory/sources/grl-radio-browser.gresource.xml b/src/lua-factory/sources/grl-radio-browser.gresource.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4f843a2833b3120a16161973dec4fbfa43c28d32
--- /dev/null
+++ b/src/lua-factory/sources/grl-radio-browser.gresource.xml
@@ -0,0 +1,6 @@
+
+
+
+ radio-browser.png
+
+
diff --git a/src/lua-factory/sources/grl-radio-browser.lua b/src/lua-factory/sources/grl-radio-browser.lua
new file mode 100644
index 0000000000000000000000000000000000000000..c88202d6813ce01eaf016dcc458c18b782abf5de
--- /dev/null
+++ b/src/lua-factory/sources/grl-radio-browser.lua
@@ -0,0 +1,258 @@
+--[[
+ * Copyright (C) 2018 Thiago Mendes
+ *
+ * Contact: Thiago Mendes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+--]]
+
+---------------------------
+-- Source initialization --
+---------------------------
+
+source = {
+ id = "grl-radio-browser-lua",
+ name = "Radio Browser",
+ description = "A community with the aim of collecting as many internet radio stations as possible",
+ supported_keys = { "title", "id", "radio-browser-station-counter",
+ "radio-browser-country", "url", "bitrate", "genres", "thumbnail",
+ "radio-browser-state", "radio-browser-upvotes",
+ "radio-browser-downvotes", "radio-browser-clickcounter" },
+ supported_media = 'audio',
+ tags = { 'radio', 'net:internet', 'net:plaintext' }
+}
+
+-------------------
+-- API RESOURCES --
+-------------------
+-- api max itens
+MAX_ITENS = 100
+
+-- api top X
+API_TOP = 10
+
+-- api urls
+api_main_url = "http://www.radio-browser.info/webservice/json"
+api_search_url = "http://www.radio-browser.info/webservice/json/stations"
+
+api_main_endpoints = {
+ countries = {
+ id = string.format("%s/%s", api_main_url, "countries"),
+ title = "List of countries",
+ search_key = "bycountry"
+ },
+ codecs = {
+ id = string.format("%s/%s", api_main_url, "codecs"),
+ title = "List of codecs",
+ search_key = "bycodec"
+ },
+ states = {
+ id = string.format("%s/%s", api_main_url, "states"),
+ title = "List of states",
+ search_key = "bystate"
+ },
+ languages = {
+ id = string.format("%s/%s", api_main_url, "languages"),
+ title = "List of languages",
+ search_key = "bylanguage"
+ },
+ tags = {
+ id = string.format("%s/%s", api_main_url, "tags"),
+ title = "List of tags",
+ search_key = "bytag"
+ },
+ stations = {
+ id = string.format("%s/%s", api_main_url, "stations"),
+ title = "List of all radio stations"
+ },
+ clicks = {
+ id = string.format("%s/%s/%d", api_main_url, "stations/topclick", API_TOP),
+ title = "Stations by clicks"
+ },
+ votes = {
+ id = string.format("%s/%s/%d", api_main_url, "stations/topvote", API_TOP),
+ title = "Stations by votes"
+ },
+ lastclick = {
+ id = string.format("%s/%s/%d", api_main_url, "stations/lastclick" , API_TOP),
+ title = "Stations by recent click"
+ },
+ lastchange = {
+ id = string.format("%s/%s/%d", api_main_url, "stations/lastchange", API_TOP),
+ title = "Stations by recently changed/added"
+ }
+}
+
+------------------
+-- Source utils --
+------------------
+
+function grl_source_browse(media_id)
+ local skip = grl.get_options("skip")
+
+ -- TODO Remove if - Right now, we need this in order to work with Rhythmbox
+ if skip > 0 then
+ grl.callback()
+ return
+ end
+
+ if not media_id then
+ for _, endpoint in pairs(api_main_endpoints) do
+ local item = create_item(endpoint)
+ grl.callback(item, -1)
+ end
+ grl.callback()
+ return
+ end
+
+ local count = grl.get_options("count")
+
+ if count <= 0 then
+ count = MAX_ITENS
+ end
+
+ local url = string.format("%s%s%s", media_id, "?", "hidenbroken=true")
+
+ grl.fetch(url, radio_browser_now_fetch_cb, media_id)
+end
+
+------------------------
+-- Callback functions --
+------------------------
+
+-- return all the media found
+function radio_browser_now_fetch_cb(result, media_id)
+ local count = grl.get_options("count")
+
+ local json = {}
+ jsons = grl.lua.json.string_to_table(result)
+
+ for _, json in pairs(jsons) do
+ local media = create_media(json, media_id)
+ if media then
+ count = count - 1
+ grl.callback(media, count)
+ else
+ grl.warning("Can't parse media")
+ end
+
+ if count == 0 then
+ return
+ end
+ end
+ grl.callback()
+end
+
+-------------
+-- Helpers --
+-------------
+
+-- User first options --
+function create_item(item)
+ local option = {}
+ option.type = "container"
+ option.id = item.id
+ option.title = item.title
+ return option
+end
+
+-- Container list
+function generate_container(json, search_key)
+ local media = {}
+ media.type = "container"
+ if json.value and string.len(json.value) > 0 then
+ media.title = json.value
+ media.id = string.format("%s/%s/%s", api_search_url, search_key, json.value)
+ end
+ -- Plugin Specific Keys
+ if json.stationcount and string.len(json.stationcount) > 0 then
+ media.radio_browser_station_counter = json.stationcount
+ end
+ if json.country and string.len(json.country) > 0 then
+ media.radio_browser_country = json.country
+ end
+ return media
+end
+
+-- Media list
+function generate_list_media(json)
+ local media = {}
+ media.type = "audio"
+ media.mime_type = "audio/mpeg"
+ -- Grilo Metadata keys
+ if json.url and string.len(json.url) > 0 then
+ media.url = json.url
+ else
+ return nil
+ end
+ if json.name and string.len(json.name) > 0 then
+ media.title = json.name
+ end
+ if json.id and string.len(json.id) > 0 then
+ media.id = json.stationuuid
+ end
+ if json.bitrate and string.len(json.bitrate) > 0 then
+ media.bitrate = json.bitrate
+ end
+ if json.tags and string.len(json.tags) > 0 then
+ media.genres = json.tags
+ end
+ if json.favicon and string.len(json.favicon) > 0 then
+ media.thumbnail = json.favicon
+ end
+ -- Plugin Specific keys
+ if json.codec and string.len(json.codec) > 0 then
+ media.radio_browser_audio_codec = json.codec
+ end
+ if json.country and string.len(json.country) > 0 then
+ media.radio_browser_country = json.country
+ end
+ if json.state and string.len(json.state) > 0 then
+ media.radio_browser_state = json.state
+ end
+ if json.language and string.len(json.language) > 0 then
+ media.radio_browser_language = json.language
+ end
+ if json.votes and string.len(json.votes) > 0 then
+ media.radio_browser_upvotes = json.votes
+ end
+ if json.negativevotes and string.len(json.negativevotes) > 0 then
+ media.radio_browser_downvotes = json.negativevotes
+ end
+ if json.clickcount and string.len(json.clickcount) > 0 then
+ media.radio_browser_clickcounter = json.clickcount
+ end
+ return media
+end
+
+function create_media(json, id)
+ if id == api_main_endpoints.countries.id then
+ return generate_container(json, api_main_endpoints.countries.search_key)
+ elseif id == api_main_endpoints.codecs.id then
+ return generate_container(json, api_main_endpoints.codecs.search_key)
+ elseif id == api_main_endpoints.states.id then
+ return generate_container(json, api_main_endpoints.states.search_key)
+ elseif id == api_main_endpoints.languages.id then
+ return generate_container(json, api_main_endpoints.languages.search_key)
+ elseif id == api_main_endpoints.tags.id then
+ return generate_container(json, api_main_endpoints.tags.search_key)
+ else
+ return generate_list_media(json)
+ end
+ grl.warning("Unknown type of media")
+ return nil
+end
diff --git a/src/lua-factory/sources/meson.build b/src/lua-factory/sources/meson.build
index 99783929f4d490533c817501d2e6fd68ffa8e258..91063fd536df3501f476bf494fa8d8cd42de51d2 100644
--- a/src/lua-factory/sources/meson.build
+++ b/src/lua-factory/sources/meson.build
@@ -14,6 +14,7 @@ sources = [
'grl-lastfm-cover',
'grl-musicbrainz',
'grl-pocket',
+ 'grl-radio-browser',
'grl-radiofrance',
'grl-spotify-cover',
'grl-theaudiodb-cover',
@@ -24,6 +25,7 @@ sources = [
resources = [
'grl-euronews',
'grl-guardianvideos',
+ 'grl-radio-browser',
'grl-radiofrance',
'grl-pocket',
'grl-appletrailers',
diff --git a/src/lua-factory/sources/radio-browser.png b/src/lua-factory/sources/radio-browser.png
new file mode 100644
index 0000000000000000000000000000000000000000..dfec572ac58d1480f7fcd7dbd467a450f9248630
Binary files /dev/null and b/src/lua-factory/sources/radio-browser.png differ