]> git.sesse.net Git - vlc/blob - share/lua/sd/icast.lua
input: stream_memory: handle skip reads
[vlc] / share / lua / sd / icast.lua
1 --[[
2  $Id$
3
4  Copyright © 2010 VideoLAN and AUTHORS
5
6  Authors: Julien 'Lta' BALLET <contact at lta dot io>
7
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 --]]
22 local config = {}
23       config["base_url"]     = "http://api.icast.io"
24       config["api_base_url"] = config.base_url.."/1"
25
26 local json   = nil
27 local roots  = nil
28
29 function json_init()
30     if json ~= nil then return false end
31
32     vlc.msg.dbg("JSON parser lazy initialization")
33     json = require ("dkjson")
34
35     -- Use vlc.stream to grab a remote json file, place it in a string,
36     -- decode it and return the decoded data.
37     json["parse_url"] = function(url)
38         local stream = vlc.stream(url)
39         local string = ""
40         local line   = ""
41
42         repeat
43             line = stream:readline()
44             string = string..line
45         until line ~= nil
46
47         --print(string)
48         return json.decode(string)
49     end
50 end
51
52 -- VLC SD mandatory method, return the name and capabilities of this SD.
53 function descriptor()
54     return { title = "iCast Stream Directory", capabilities = {"search"} }
55 end
56
57 -- Utility function to replace nils by an empty string, borrowed from icecast.lua
58 function dropnil(s)
59     if s == nil then return "" else return s end
60 end
61
62 function roots_init()
63     if roots ~= nil then return nil end
64
65     roots = {
66         locals  = vlc.sd.add_node({title="Local Streams"}),
67         cats    = vlc.sd.add_node({title="Categories"}),
68         search  = nil
69     }
70 end
71
72 -- Add this station to the discovered service list.
73 function station_add(node, station)
74     if station.streams == nil or station.streams[1] == nil then
75         return nil
76     end
77
78     item = node:add_subitem({
79         title = station.name,
80         path  = station.streams[1]["uri"],
81         meta  = {
82             ["Listing Source"]  = "icast.io",
83             ["Listing Type"]    = "radio",
84             ["Icecast Bitrate"] = dropnil(station.streams[1].bitrate)
85         }
86     })
87
88     if station.slogan then
89         item:set_name(station.name..": "..station.slogan)
90     end
91     if station.genre_list then
92         item:set_genre(table.concat(station.genre_list, ", "))
93     end
94     if station.language then
95         item:set_language(station.language)
96     end
97     if station.logo.medium then
98         item:set_arturl(config.base_url..station.logo.medium)
99     end
100 end
101
102 -- Get an url to iCast's API, parse the returned stations and add them
103 -- to the list of discovered medias.
104 function stations_fetch(node, url)
105     json_init()
106     vlc.msg.info("Fetching stations from API ("..url..")")
107
108     local result = json.parse_url(config.api_base_url..url)
109
110     if result.stations == nil then
111         return nil
112     end
113
114     for _, station in ipairs(result.stations) do
115         station_add(node, station)
116     end
117 end
118
119 -- VLC SD API - Search entry point
120 function search(query)
121     if roots.search then vlc.sd.remove_node(roots.search) end
122
123     roots.search = vlc.sd.add_node({title="Search Results"})
124
125     stations_fetch(roots.search, "/stations/search.json?q="..query.."*")
126 end
127
128 -- VLC SD API - Main listing entry point
129 function main()
130     roots_init()
131
132     stations_fetch(roots.locals, "/stations/local.json")
133
134     vlc.msg.dbg("Fetching list of genre from API (/genres.json)")
135     local result = json.parse_url(config.api_base_url.."/genres.json")
136     for genre, sub_genres in pairs(result.genres) do
137         local node = roots.cats:add_subnode({title=genre})
138         for _, sub_genre in ipairs(sub_genres) do
139             local sub_node = node:add_subnode({title=sub_genre})
140             stations_fetch(sub_node, "/stations/genre/"..sub_genre..".json")
141         end
142     end
143 end