From cc1817e07534aafcc04cbb8c180465b25bc4214c Mon Sep 17 00:00:00 2001 From: Thiago Mendes Date: Fri, 28 Sep 2018 12:34:36 +0200 Subject: [PATCH 1/2] lua-plugins: Add support to radio-browswer.info Add a lua plugin to fetch data from the radio-browser.info api issue #21 --- .../sources/grl-radio-browser.gresource.xml | 6 + src/lua-factory/sources/grl-radio-browser.lua | 310 ++++++++++++++++++ src/lua-factory/sources/meson.build | 2 + src/lua-factory/sources/radio-browser.png | Bin 0 -> 14640 bytes 4 files changed, 318 insertions(+) create mode 100644 src/lua-factory/sources/grl-radio-browser.gresource.xml create mode 100644 src/lua-factory/sources/grl-radio-browser.lua create mode 100644 src/lua-factory/sources/radio-browser.png 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 00000000..4f843a28 --- /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 00000000..b45f06f3 --- /dev/null +++ b/src/lua-factory/sources/grl-radio-browser.lua @@ -0,0 +1,310 @@ +--[[ + * 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 = { "country", "codecs", "states", "languages", "tags" }, + icon = 'resource:///org/gnome/grilo/plugins/radiofrance/radiofrance.png', + supported_media = 'audio', + tags = { 'radio', 'net:internet', 'net:plaintext' } +} + +------------------- +-- API RESOURCES -- +------------------- +-- Max items +MAX_ITEMS = 100 + +-- api top X +API_TOP = 10 + +-- do not count broken stations +api_hidebroken = false + +-- 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 = { + { + id = string.format("%s/%s", api_main_url, "countries"), + title = "List of countries" + }, + { + id = string.format("%s/%s", api_main_url, "codecs"), + title = "List of codecs" + }, + { + id = string.format("%s/%s", api_main_url, "states"), + title = "List of states" + }, + { + id = string.format("%s/%s", api_main_url, "languages"), + title = "List of languages" + }, + { + id = string.format("%s/%s", api_main_url, "tags"), + title = "List of tags" + }, + { + id = string.format("%s/%s", api_main_url, "stations"), + title = "List of all radio stations" + }, + { + id = string.format("%s/%s/%d", api_main_url, "stations/topclick", API_TOP), + title = "Stations by clicks" + }, + { + id = string.format("%s/%s/%d", api_main_url, "stations/topvote", API_TOP), + title = "Stations by votes" + }, + { + id = string.format("%s/%s/%d", api_main_url, "stations/lastclick" , API_TOP), + title = "Stations by recent click" + }, + { + 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) + if media_id == nil then + for _, endpoint in ipairs(api_main_endpoints) do + local usr_opt = create_item(endpoint) + grl.callback(usr_opt, -1) + end + grl.callback() + return + end + + local count = grl.get_options("count") + local skip = grl.get_options("skip") + + if skip + count > MAX_ITEMS then + grl.callback() + return + end + + local url = string.format("%s?offset=%d&limit=%d", media_id, skip, MAX_ITEMS) + if (api_hidebroken) then + url = url.."&hidebroken=true" + end + grl.fetch(url, grl_radio_browser_now_fetch_cb, media_id) +end + +------------------------ +-- Callback functions -- +------------------------ + +-- return all the media found +function grl_radio_browser_now_fetch_cb(results, media_id) + local count = grl.get_options("count") + local skip = grl.get_options("skip") + + local json = {} + json = grl.lua.json.string_to_table(results) + + for _, item in pairs(json) do + if skip > 0 then + skip = skip - 1 + elseif count > 0 then + local media = create_media(item, media_id) + if media then + grl.callback(media, count) + count = count - 1 + end + 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 + +-- List of countries -- +function generate_list_countries(json) + local media = {} + media.type = "container" + if json.value and string.len(json.value) > 0 then + media.title = json.value + media.id = api_search_url .. "/bycountry/" .. json.value + end + -- Plugin Specific info + if json.stationcount and string.len(json.stationcount) > 0 then + media.grl_radio_browser_station_counter = json.stationcount + end + return media +end + +-- List of codecs -- +function generate_list_codecs(json) + local media = {} + media.type = "container" + if json.value and string.len(json.value) > 0 then + media.title = json.value + media.id = api_search_url .. "/bycodec/" .. json.value + end + -- Plugin Specific info + if json.stationcount and string.len(json.stationcount) > 0 then + media.grl_radio_browser_station_counter = json.stationcount + end + return media +end + +-- List of states -- +function generate_list_states(json) + local media = {} + media.type = "container" + if json.value and string.len(json.value) > 0 then + media.title = json.value + media.id = api_search_url .. "/bystate/" .. json.value + end + -- Plugin Specific info + if json.country and string.len(json.country) > 0 then + media.grl_radio_browser_country = json.country + end + if json.stationcount and string.len(json.stationcount) > 0 then + media.grl_radio_browser_station_counter = json.stationcount + end + return media +end + +-- List of languages +function generate_list_languages(json) + local media = {} + media.type = "container" + if json.value and string.len(json.value) > 0 then + media.title = json.value + media.id = api_search_url .. "/bylanguage/" .. json.value + end + -- Plugin Specific info + if json.stationcount and string.len(json.stationcount) > 0 then + media.grl_radio_browser_station_counter = json.stationcount + end + return media +end + +-- List of tags +function generate_list_tags(json) + local media = {} + media.type = "container" + if json.value and string.len(json.value) > 0 then + media.title = json.value + media.id = api_search_url .. "/bytag/" .. json.value + end + -- Plugin Specific info + if json.stationcount and string.len(json.stationcount) > 0 then + media.grl_radio_browser_station_counter = json.stationcount + end + return media +end + +-- Media list +function generate_list_media(json) + local media = {} + media.type = "audio" + media.mime_type = "audio/mpeg" + 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.url and string.len(json.url) > 0 then + media.url = json.url + 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 info + if json.codec and string.len(json.codec) > 0 then + media.grl_radio_browser_audio_codec = json.codec + end + if json.country and string.len(json.country) > 0 then + media.grl_radio_browser_country = json.country + end + if json.state and string.len(json.state) > 0 then + media.grl_radio_browser_state = json.state + end + if json.language and string.len(json.language) > 0 then + media.grl_radio_browser_language = json.language + end + if json.votes and string.len(json.votes) > 0 then + media.grl_radio_browser_upvotes = json.votes + end + if json.negativevotes and string.len(json.negativevotes) > 0 then + media.grl_radio_browser_downvotes = json.negativevotes + end + if json.clickcount and string.len(json.clickcount) > 0 then + media.grl_radio_browser_clickcounter = json.clickcount + end + return media +end + +function create_media(json, id) + if id == api_main_endpoints[1].id then + return generate_list_countries(json) + elseif id == api_main_endpoints[2].id then + return generate_list_codecs(json) + elseif id == api_main_endpoints[3].id then + return generate_list_states(json) + elseif id == api_main_endpoints[4].id then + return generate_list_languages(json) + elseif id == api_main_endpoints[5].id then + return generate_list_tags(json) + else + return generate_list_media(json) + end + return nil +end diff --git a/src/lua-factory/sources/meson.build b/src/lua-factory/sources/meson.build index 99783929..91063fd5 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 GIT binary patch literal 14640 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 Date: Fri, 28 Sep 2018 17:02:34 +0200 Subject: [PATCH 2/2] lua-plugins: Code cleanup and bug fixes * Reduce the number of helper functions * Better use of the api map variable * Map all the supported keys * Check for skip equal to zero on the browser callback --- src/lua-factory/sources/grl-radio-browser.lua | 268 +++++++----------- 1 file changed, 108 insertions(+), 160 deletions(-) diff --git a/src/lua-factory/sources/grl-radio-browser.lua b/src/lua-factory/sources/grl-radio-browser.lua index b45f06f3..c88202d6 100644 --- a/src/lua-factory/sources/grl-radio-browser.lua +++ b/src/lua-factory/sources/grl-radio-browser.lua @@ -28,8 +28,10 @@ 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 = { "country", "codecs", "states", "languages", "tags" }, - icon = 'resource:///org/gnome/grilo/plugins/radiofrance/radiofrance.png', + 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' } } @@ -37,60 +39,62 @@ source = { ------------------- -- API RESOURCES -- ------------------- --- Max items -MAX_ITEMS = 100 +-- api max itens +MAX_ITENS = 100 -- api top X API_TOP = 10 --- do not count broken stations -api_hidebroken = false - -- 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 = { - { - id = string.format("%s/%s", api_main_url, "countries"), - title = "List of countries" - }, - { - id = string.format("%s/%s", api_main_url, "codecs"), - title = "List of codecs" - }, - { - id = string.format("%s/%s", api_main_url, "states"), - title = "List of states" - }, - { - id = string.format("%s/%s", api_main_url, "languages"), - title = "List of languages" - }, - { - id = string.format("%s/%s", api_main_url, "tags"), - title = "List of tags" - }, - { - id = string.format("%s/%s", api_main_url, "stations"), - title = "List of all radio stations" - }, - { - id = string.format("%s/%s/%d", api_main_url, "stations/topclick", API_TOP), - title = "Stations by clicks" - }, - { - id = string.format("%s/%s/%d", api_main_url, "stations/topvote", API_TOP), - title = "Stations by votes" - }, - { - id = string.format("%s/%s/%d", api_main_url, "stations/lastclick" , API_TOP), - title = "Stations by recent click" - }, - { - id = string.format("%s/%s/%d", api_main_url, "stations/lastchange", API_TOP), - title = "Stations by recently changed/added" - } + 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" + } } ------------------ @@ -98,28 +102,32 @@ api_main_endpoints = { ------------------ function grl_source_browse(media_id) - if media_id == nil then - for _, endpoint in ipairs(api_main_endpoints) do - local usr_opt = create_item(endpoint) - grl.callback(usr_opt, -1) + 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") - local skip = grl.get_options("skip") - if skip + count > MAX_ITEMS then - grl.callback() - return + if count <= 0 then + count = MAX_ITENS end - local url = string.format("%s?offset=%d&limit=%d", media_id, skip, MAX_ITEMS) - if (api_hidebroken) then - url = url.."&hidebroken=true" - end - grl.fetch(url, grl_radio_browser_now_fetch_cb, media_id) + local url = string.format("%s%s%s", media_id, "?", "hidenbroken=true") + + grl.fetch(url, radio_browser_now_fetch_cb, media_id) end ------------------------ @@ -127,23 +135,24 @@ end ------------------------ -- return all the media found -function grl_radio_browser_now_fetch_cb(results, media_id) +function radio_browser_now_fetch_cb(result, media_id) local count = grl.get_options("count") - local skip = grl.get_options("skip") local json = {} - json = grl.lua.json.string_to_table(results) + jsons = grl.lua.json.string_to_table(result) - for _, item in pairs(json) do - if skip > 0 then - skip = skip - 1 - elseif count > 0 then - local media = create_media(item, media_id) - if media then - grl.callback(media, count) - count = count - 1 - end - end + 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 @@ -161,80 +170,20 @@ function create_item(item) return option end --- List of countries -- -function generate_list_countries(json) +-- 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 = api_search_url .. "/bycountry/" .. json.value + media.id = string.format("%s/%s/%s", api_search_url, search_key, json.value) end - -- Plugin Specific info + -- Plugin Specific Keys if json.stationcount and string.len(json.stationcount) > 0 then - media.grl_radio_browser_station_counter = json.stationcount + media.radio_browser_station_counter = json.stationcount end - return media -end - --- List of codecs -- -function generate_list_codecs(json) - local media = {} - media.type = "container" - if json.value and string.len(json.value) > 0 then - media.title = json.value - media.id = api_search_url .. "/bycodec/" .. json.value - end - -- Plugin Specific info - if json.stationcount and string.len(json.stationcount) > 0 then - media.grl_radio_browser_station_counter = json.stationcount - end - return media -end - --- List of states -- -function generate_list_states(json) - local media = {} - media.type = "container" - if json.value and string.len(json.value) > 0 then - media.title = json.value - media.id = api_search_url .. "/bystate/" .. json.value - end - -- Plugin Specific info if json.country and string.len(json.country) > 0 then - media.grl_radio_browser_country = json.country - end - if json.stationcount and string.len(json.stationcount) > 0 then - media.grl_radio_browser_station_counter = json.stationcount - end - return media -end - --- List of languages -function generate_list_languages(json) - local media = {} - media.type = "container" - if json.value and string.len(json.value) > 0 then - media.title = json.value - media.id = api_search_url .. "/bylanguage/" .. json.value - end - -- Plugin Specific info - if json.stationcount and string.len(json.stationcount) > 0 then - media.grl_radio_browser_station_counter = json.stationcount - end - return media -end - --- List of tags -function generate_list_tags(json) - local media = {} - media.type = "container" - if json.value and string.len(json.value) > 0 then - media.title = json.value - media.id = api_search_url .. "/bytag/" .. json.value - end - -- Plugin Specific info - if json.stationcount and string.len(json.stationcount) > 0 then - media.grl_radio_browser_station_counter = json.stationcount + media.radio_browser_country = json.country end return media end @@ -244,6 +193,7 @@ 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 @@ -255,9 +205,6 @@ function generate_list_media(json) if json.id and string.len(json.id) > 0 then media.id = json.stationuuid end - if json.url and string.len(json.url) > 0 then - media.url = json.url - end if json.bitrate and string.len(json.bitrate) > 0 then media.bitrate = json.bitrate end @@ -267,44 +214,45 @@ function generate_list_media(json) if json.favicon and string.len(json.favicon) > 0 then media.thumbnail = json.favicon end - -- Plugin Specific info + -- Plugin Specific keys if json.codec and string.len(json.codec) > 0 then - media.grl_radio_browser_audio_codec = json.codec + media.radio_browser_audio_codec = json.codec end if json.country and string.len(json.country) > 0 then - media.grl_radio_browser_country = json.country + media.radio_browser_country = json.country end if json.state and string.len(json.state) > 0 then - media.grl_radio_browser_state = json.state + media.radio_browser_state = json.state end if json.language and string.len(json.language) > 0 then - media.grl_radio_browser_language = json.language + media.radio_browser_language = json.language end if json.votes and string.len(json.votes) > 0 then - media.grl_radio_browser_upvotes = json.votes + media.radio_browser_upvotes = json.votes end if json.negativevotes and string.len(json.negativevotes) > 0 then - media.grl_radio_browser_downvotes = json.negativevotes + media.radio_browser_downvotes = json.negativevotes end if json.clickcount and string.len(json.clickcount) > 0 then - media.grl_radio_browser_clickcounter = json.clickcount + media.radio_browser_clickcounter = json.clickcount end return media end function create_media(json, id) - if id == api_main_endpoints[1].id then - return generate_list_countries(json) - elseif id == api_main_endpoints[2].id then - return generate_list_codecs(json) - elseif id == api_main_endpoints[3].id then - return generate_list_states(json) - elseif id == api_main_endpoints[4].id then - return generate_list_languages(json) - elseif id == api_main_endpoints[5].id then - return generate_list_tags(json) + 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 -- GitLab