aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--awesompd.lua179
-rw-r--r--jamendo.lua237
2 files changed, 261 insertions, 155 deletions
diff --git a/awesompd.lua b/awesompd.lua
index 8c6d382..8243542 100644
--- a/awesompd.lua
+++ b/awesompd.lua
@@ -5,6 +5,8 @@
---------------------------------------------------------------------------
require('utf8')
+require('jamendo')
+
local naughty = naughty
local awful = awful
@@ -78,7 +80,6 @@ function awesompd:create()
instance.status_text = "Stopped"
instance.to_notify = false
instance.connected = true
- instance.jamendo_list = {}
instance.recreate_menu = true
instance.recreate_playback = true
@@ -95,7 +96,6 @@ function awesompd:create()
instance.output_size = 30
instance.update_interval = 10
instance.path_to_icons = ""
- instance.filename = awful.util.getdir ("cache").."/jamendo_cache"
instance.ldecorator = " "
instance.rdecorator = " "
@@ -112,7 +112,6 @@ end
-- Registers timers for the widget
function awesompd:run()
enable_dbg = self.debug_mode
- self:retrieve_cache()
self:update_track()
self:check_playlists()
self.load_icons(self.path_to_icons)
@@ -301,43 +300,31 @@ function awesompd:command_show_menu()
end
end
-function awesompd:add_tracks_from_jamendo(parse_table,format)
- if (table.getn(parse_table) > 0) then
- local trygetlink =
- assert(io.popen("echo $(curl -w %{redirect_url} " ..
- "'http://api.jamendo.com/get2/stream/track/redirect/" ..
- "?streamencoding="..format.."&id=729304')"),'r'):read("*lines")
- local _, _, prefix = string.find(trygetlink,"stream(%d+)\.jamendo\.com")
- for i = 1,table.getn(parse_table) do
- track_link = "http://stream" .. prefix .. ".jamendo.com/stream/"
- .. parse_table[i].id .."/".. format .."/"
- self:command("add " .. track_link)
- self.jamendo_list[parse_table[i].id] =
- parse_table[i].artist .. " - " .. parse_table[i].track
- end
- end
-end
+-- function awesompd:add_tracks_from_jamendo(parse_table,format)
+-- if (table.getn(parse_table) > 0) then
+-- local trygetlink =
+-- assert(io.popen("echo $(curl -w %{redirect_url} " ..
+-- "'http://api.jamendo.com/get2/stream/track/redirect/" ..
+-- "?streamencoding="..format.."&id=729304')"),'r'):read("*lines")
+-- local _, _, prefix = string.find(trygetlink,"stream(%d+)\.jamendo\.com")
+-- for i = 1,table.getn(parse_table) do
+-- track_link = "http://stream" .. prefix .. ".jamendo.com/stream/"
+-- .. parse_table[i].id .."/".. format .."/"
+-- self:command("add " .. track_link)
+-- self.jamendo_list[parse_table[i].id] =
+-- parse_table[i].artist .. " - " .. parse_table[i].track
+-- end
+-- end
+-- end
function awesompd:add_jamendo_top(format)
return function ()
- local top_list = "curl -A 'Mozilla/4.0' -fsm 5 \"http://api.jamendo.com/get2/" ..
- "id+name+url+stream+album_name+album_url+album_id+artist_id+artist_name" ..
- "/track/jsonpretty/track_album+album_artist/?n=100&order=ratingweek_desc\""
- local bus = assert(io.popen(top_list, 'r'))
- local r = bus:read("*all")
- bus:close()
- local parse_table = {}
- string.gsub(r, "\"id\":(%d+),%s+\"name\":\"([^\"]+)[^%}]*\"artist_name\":\"([^\"]+)\"",
- function(_id,_track,_artist)
- table.insert(parse_table,
- { id = _id,
- track = (_track or ""),
- artist = (_artist or "")})
- end)
- self:add_tracks_from_jamendo(parse_table,format)
+ local track_table = jamendo.return_track_table()
+ for i = 1,table.getn(track_table) do
+ self:command("add " .. track_table[i].stream)
+ end
self.recreate_menu = true
self.recreate_list = true
- self:save_cache()
end
end
@@ -384,7 +371,7 @@ function awesompd:get_list_menu()
local end_num = (self.current_number + 15 < total_count ) and self.current_number + 15 or total_count
for i = start_num, end_num do
if (string.find(self.list_array[i],"jamendo.com")) then
- table.insert(new_menu, { self.jamendo_list[awesompd.get_id_from_link(self.list_array[i])],
+ table.insert(new_menu, { jamendo.get_name_by_link(self.list_array[i]),
self:command_play_specific(i),
self.current_number == i and
(self.status == "Playing" and self.ICONS.PLAY or self.ICONS.PAUSE)
@@ -550,34 +537,6 @@ function awesompd:wrap_output(text)
awesompd.protect_string(text), self.rdecorator)
end
--- Retrieves mapping of track IDs to track names to avoid redundant
--- queries when Awesome gets restarted.
-function awesompd:retrieve_cache()
- local bus = io.open(self.filename)
- if bus then
- for l in bus:lines() do
- local _, _, id, track = string.find(l,"(%d+)-(.+)")
- self.jamendo_list[id] = track
- end
- end
-end
-
--- Saves track IDs to track names mapping into the cache file.
-function awesompd:save_cache()
- local bus = io.open(self.filename, "w")
- for id,name in pairs(self.jamendo_list) do
- bus:write(id.."-"..name.."\n")
- end
- bus:flush()
- bus:close()
-end
-
--- Returns the track ID from the given link to Jamendo stream.
-function awesompd.get_id_from_link(link)
- local _, _, id = string.find(link,"stream/(%d+)")
- return id
-end
-
function awesompd.split (s,t)
local l = {n=0}
local f = function (s)
@@ -687,7 +646,7 @@ function awesompd:update_track(file)
local new_track = track_line
if new_track ~= self.unique_text then
if (string.find(new_track,"jamendo.com")) then
- self.text = self.jamendo_list[awesompd.get_id_from_link(new_track)]
+ self.text = jamendo.get_name_by_link(new_track)
else
self.text = new_track
end
@@ -762,93 +721,3 @@ function awesompd.protect_string(str, for_menu)
return utf8replace(str, awesompd.ESCAPE_SYMBOL_MAPPING)
end
end
-
--- Primitive function for parsing Jamendo API JSON response. Does not
--- support arrays. Supports only strings and numbers as values.
--- Provides basic safety (correctly handles special symbols like comma
--- and curly brackets inside strings)
--- text - JSON text
-function awesompd.parse_json(text)
- local parse_table = {}
- local block = {}
- local i = 0
- local inblock = false
- local instring = false
- local curr_key = nil
- local curr_val = nil
- while i and i < string.len(text) do
- if not inblock then -- We are not inside the block, find next {
- i = string.find(text, "{", i+1)
- inblock = true
- block = {}
- else
- if not curr_key then -- We haven't found key yet
- if not instring then -- We are not in string, check for more tags
- local j = string.find(text, '"', i+1)
- local k = string.find(text, '}', i+1)
- if j and j < k then -- There are more tags in this block
- i = j
- instring = true
- else -- Block is over, find its ending
- i = k
- inblock = false
- table.insert(parse_table, block)
- end
- else -- We are in string, find its ending
- _, i, curr_key = string.find(text,'(.-[^%\\])"', i+1)
- instring = false
- end
- else -- We have the key, let's find the value
- if not curr_val then -- Value is not found yet
- if not instring then -- Not in string, check if value is string
- local j = string.find(text, '"', i+1)
- local k = string.find(text, '[,}]', i+1)
- if j and j < k then -- Value is string
- i = j
- instring = true
- else -- Value is int
- _, i, curr_val = string.find(text,'(%d+)', i+1)
- end
- else -- We are in string, find its ending
- local j = string.find(text, '"', i+1)
- if j == i+1 then -- String is empty
- i = j
- curr_val = ""
- else
- _, i, curr_val = string.find(text,'(.-[^%\\])"', i+1)
- curr_val = awesompd.utf8_codes_to_symbols(curr_val)
- end
- instring = false
- end
- else -- We have both key and value, add it to table
- block[curr_key] = curr_val
- curr_key = nil
- curr_val = nil
- end
- end
- end
- end
- return parse_table
-end
-
--- Jamendo returns Unicode symbols as \uXXXX. Lua does not transform
--- them into symbols so we need to do it ourselves.
-function awesompd.utf8_codes_to_symbols (s)
- local hexnums = "[%dabcdefABCDEF]"
- local pattern = string.format("\\u(%s%s%s%s?)",
- hexnums, hexnums, hexnums, hexnums)
- print("Pattern is : " .. pattern)
- local decode = function(code)
- code = tonumber(code, 16)
- -- Grab high and low byte
- local hi = math.floor(code / 256) * 4 + 192
- local lo = math.mod(code, 256)
- -- Reduce low byte to 64, add overflow to high
- local oflow = math.floor(lo / 64)
- hi = hi + oflow
- lo = math.mod(code, 64) + 128
- -- Return symbol as \hi\lo
- return string.char(hi, lo)
- end
- return string.gsub(s, pattern, decode)
-end
diff --git a/jamendo.lua b/jamendo.lua
new file mode 100644
index 0000000..1f4a915
--- /dev/null
+++ b/jamendo.lua
@@ -0,0 +1,237 @@
+module('jamendo', package.seeall)
+
+-- Grab environment
+local os = os
+
+-- Global variables
+FORMAT_MP3 = { display = "MP3 (128k)",
+ short_display = "MP3",
+ value = "mp31" }
+FORMAT_OGG = { display = "Ogg Vorbis (q4)",
+ short_display = "Ogg",
+ value = "ogg2" }
+ORDER_RATINGDAILY = { display = "Daily rating",
+ short_display = "daily rating",
+ value = "ratingday_desc" }
+ORDER_RATINGWEEKLY = { display = "Weekly rating",
+ short_display = "weekly rating",
+ value = "ratingweek_desc" }
+ORDER_RATINGTOTAL = { display = "All time rating",
+ short_display = "all time rating",
+ value = "ratingtotal_desc" }
+ORDER_RANDOM = { display = "Random",
+ short_display = "random",
+ value = "random_desc" }
+SEARCH_ARTIST = { display = "Artist",
+ value = "artist" }
+SEARCH_ALBUM = { display = "Album",
+ value = "album" }
+SEARCH_TAG = { display = "Tag",
+ value = "tag_idstr" }
+
+current_request_table = { format = FORMAT_MP3,
+ order = ORDER_RATINGWEEKLY }
+
+-- Local variables
+local jamendo_list = {}
+local cache_file = awful.util.getdir ("cache").."/jamendo_cache"
+local default_mp3_stream = nil
+
+-- Returns default stream number for MP3 format. Requests API for it
+-- not more often than every hour.
+function get_default_mp3_stream()
+ if not default_mp3_stream or
+ (os.time() - default_mp3_stream.last_checked) > 3600 then
+ local trygetlink =
+ assert(io.popen("echo $(curl -w %{redirect_url} " ..
+ "'http://api.jamendo.com/get2/stream/track/redirect/" ..
+ "?streamencoding="..format.."&id=729304')",'r')):read("*line")
+ local _, _, prefix = string.find(trygetlink,"stream(%d+)\.jamendo\.com")
+ default_mp3_stream = { id = prefix, last_checked = os.time() }
+ end
+ return default_mp3_stream.id
+end
+
+-- Returns the track ID from the given link to Jamendo stream.
+function get_id_from_link(link)
+ local _, _, id = string.find(link,"stream/(%d+)")
+ return id
+end
+
+-- Returns link to music stream for the given track ID. Uses MP3
+-- format and the default stream for it.
+function get_link_by_id(id)
+ return string.format("http://stream%s.jamendo.com/stream/%s/mp31/",
+ get_default_mp3_stream(), id)
+end
+
+-- Returns track name for given music stream.
+function get_name_by_link(link)
+ return jamendo_list[get_id_from_link(link)]
+end
+
+-- Returns table of track IDs, names and other things based on the
+-- request table.
+function return_track_table(request_table)
+ local req_string = form_request(request_table)
+ local bus = assert(io.popen(req_string, 'r'))
+ local response = bus:read("*all")
+ bus:close()
+ parse_table = parse_json(response)
+ for i = 1, table.getn(parse_table) do
+ if parse_table[i].stream == "" then
+ -- Some songs don't have Ogg stream, use MP3 instead
+ parse_table[i].stream = get_link_by_id(parse_table[i].id)
+ end
+ parse_table[i].display_name =
+ parse_table[i].artist_name .. " - " .. parse_table[i].name
+ -- Save fetched tracks for further caching
+ jamendo_list[parse_table[i].id] = parse_table[i].display_name
+ end
+ save_cache()
+ return parse_table
+end
+
+-- Generates the request to Jamendo API based on provided request
+-- table. If request_table is nil, uses current_request_table instead.
+function form_request(request_table)
+ local curl_str = 'echo $(curl -w %%{redirect_url} ' ..
+ '"http://api.jamendo.com/get2/id+artist_name+name+stream/' ..
+ 'track/json/track_album+album_artist/?n=100&order=%s&streamencoding=%s")'
+ if request_table then
+ local format = request_table.format or current_request_table.format
+ local order = request_table.order or current_request_table.order
+ return string.format(curl_str, order.value, format.value)
+ else
+ print("Request : " .. string.format(curl_str,
+ current_request_table.order.value,
+ current_request_table.format.value))
+ return string.format(curl_str,
+ current_request_table.order.value,
+ current_request_table.format.value)
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+-- Primitive function for parsing Jamendo API JSON response. Does not
+-- support arrays. Supports only strings and numbers as values.
+-- Provides basic safety (correctly handles special symbols like comma
+-- and curly brackets inside strings)
+-- text - JSON text
+function parse_json(text)
+ local parse_table = {}
+ local block = {}
+ local i = 0
+ local inblock = false
+ local instring = false
+ local curr_key = nil
+ local curr_val = nil
+ while i and i < string.len(text) do
+ if not inblock then -- We are not inside the block, find next {
+ i = string.find(text, "{", i+1)
+ inblock = true
+ block = {}
+ else
+ if not curr_key then -- We haven't found key yet
+ if not instring then -- We are not in string, check for more tags
+ local j = string.find(text, '"', i+1)
+ local k = string.find(text, '}', i+1)
+ if j and j < k then -- There are more tags in this block
+ i = j
+ instring = true
+ else -- Block is over, find its ending
+ i = k
+ inblock = false
+ table.insert(parse_table, block)
+ end
+ else -- We are in string, find its ending
+ _, i, curr_key = string.find(text,'(.-[^%\\])"', i+1)
+ instring = false
+ end
+ else -- We have the key, let's find the value
+ if not curr_val then -- Value is not found yet
+ if not instring then -- Not in string, check if value is string
+ local j = string.find(text, '"', i+1)
+ local k = string.find(text, '[,}]', i+1)
+ if j and j < k then -- Value is string
+ i = j
+ instring = true
+ else -- Value is int
+ _, i, curr_val = string.find(text,'(%d+)', i+1)
+ end
+ else -- We are in string, find its ending
+ local j = string.find(text, '"', i+1)
+ if j == i+1 then -- String is empty
+ i = j
+ curr_val = ""
+ else
+ _, i, curr_val = string.find(text,'(.-[^%\\])"', i+1)
+ curr_val = utf8_codes_to_symbols(curr_val)
+ end
+ instring = false
+ end
+ else -- We have both key and value, add it to table
+ block[curr_key] = curr_val
+ curr_key = nil
+ curr_val = nil
+ end
+ end
+ end
+ end
+ return parse_table
+end
+
+-- Jamendo returns Unicode symbols as \uXXXX. Lua does not transform
+-- them into symbols so we need to do it ourselves.
+function utf8_codes_to_symbols (s)
+ local hexnums = "[%dabcdefABCDEF]"
+ local pattern = string.format("\\u(%s%s%s%s?)",
+ hexnums, hexnums, hexnums, hexnums)
+ local decode = function(code)
+ code = tonumber(code, 16)
+ -- Grab high and low byte
+ local hi = math.floor(code / 256) * 4 + 192
+ local lo = math.mod(code, 256)
+ -- Reduce low byte to 64, add overflow to high
+ local oflow = math.floor(lo / 64)
+ hi = hi + oflow
+ lo = math.mod(code, 64) + 128
+ -- Return symbol as \hi\lo
+ return string.char(hi, lo)
+ end
+ return string.gsub(s, pattern, decode)
+end
+
+-- Retrieves mapping of track IDs to track names to avoid redundant
+-- queries when Awesome gets restarted.
+function retrieve_cache()
+ local bus = io.open(cache_file)
+ if bus then
+ for l in bus:lines() do
+ local _, _, id, track = string.find(l,"(%d+)-(.+)")
+ jamendo_list[id] = track
+ end
+ end
+end
+
+-- Saves track IDs to track names mapping into the cache file.
+function save_cache()
+ local bus = io.open(cache_file, "w")
+ for id,name in pairs(jamendo_list) do
+ bus:write(id.."-"..name.."\n")
+ end
+ bus:flush()
+ bus:close()
+end
+
+-- Retrieve cache on initialization
+retrieve_cache()