From 3a8fdd263de92f89d1c9fd7c15ba3c49eed39c20 Mon Sep 17 00:00:00 2001
From: Alexander Yakushev <yakushev.alex@gmail.com>
Date: Sat, 10 Sep 2011 18:03:24 +0300
Subject: Added feature to browse current artist or album on Jamendo

---
 awesompd.lua | 66 ++++++++++++++++++++++++++++++++++++-----------
 jamendo.lua  | 83 ++++++++++++++++++++++++++++++++++++++++--------------------
 rcsample.lua |  4 +++
 3 files changed, 110 insertions(+), 43 deletions(-)

diff --git a/awesompd.lua b/awesompd.lua
index 10b5442..7562873 100644
--- a/awesompd.lua
+++ b/awesompd.lua
@@ -1,7 +1,7 @@
 ---------------------------------------------------------------------------
 -- @author Alexander Yakushev <yakushev.alex@gmail.com>
 -- @copyright 2010-2011 Alexander Yakushev
--- @release v1.0.5
+-- @release v1.0.6
 ---------------------------------------------------------------------------
 
 require('utf8')
@@ -137,6 +137,7 @@ function awesompd:create()
    instance.recreate_options = true
    instance.recreate_jamendo_formats = true
    instance.recreate_jamendo_order = true
+   instance.recreate_jamendo_browse = true
    instance.current_number = 0
    instance.menu_shown = false
 
@@ -151,6 +152,7 @@ function awesompd:create()
    instance.rdecorator = " "
    instance.show_album_cover = true
    instance.album_cover_size = 50
+   instance.browser = "firefox"
    
 -- Widget configuration
    instance.widget:add_signal("mouse::enter", function(c)
@@ -287,6 +289,14 @@ function awesompd:command_clear_playlist()
              self.recreate_list = true
           end
 end
+
+function awesompd:command_open_in_browser(link)
+   return function()
+             if self.browser then
+                awful.util.spawn(self.browser .. " '" .. link .. "'")
+             end
+          end
+end
              
 
 -- /// End of mpc command functions ///
@@ -306,18 +316,23 @@ function awesompd:command_show_menu()
          self.connected then 
             self:check_list() 
             self:check_playlists()
+            local jamendo_menu = { { "Search by", 
+                                     { { "Nothing (Top 100)", self:menu_jamendo_top() },
+                                       { "Artist", self:menu_jamendo_search_by(jamendo.SEARCH_ARTIST) },
+                                       { "Album", self:menu_jamendo_search_by(jamendo.SEARCH_ALBUM) },
+                                       { "Tag", self:menu_jamendo_search_by(jamendo.SEARCH_TAG) }}} }
+            local browse_menu = self:menu_jamendo_browse()
+            if browse_menu then 
+               table.insert(jamendo_menu, browse_menu)
+            end
+            table.insert(jamendo_menu, self:menu_jamendo_format())
+            table.insert(jamendo_menu, self:menu_jamendo_order())
+
             new_menu = { { "Playback", self:menu_playback() },
                          { "Options", self:menu_options() },
                          { "List", self:menu_list() },
                          { "Playlists", self:menu_playlists() },
-                         { "Jamendo",
-                           { { "Search by", 
-                               { { "Nothing (Top 100)", self:menu_jamendo_top() },
-                                 { "Artist", self:menu_jamendo_search_by(jamendo.SEARCH_ARTIST) },
-                                 { "Album", self:menu_jamendo_search_by(jamendo.SEARCH_ALBUM) },
-                                 { "Tag", self:menu_jamendo_search_by(jamendo.SEARCH_TAG) }}},
-                             self:menu_jamendo_format(),
-                             self:menu_jamendo_order() }} }
+                         { "Jamendo", jamendo_menu } }
          end 
          table.insert(new_menu, { "Servers", self:menu_servers() }) 
          self.main_menu = awful.menu({ items = new_menu, width = 300 }) 
@@ -384,16 +399,16 @@ function awesompd:menu_list()
    if self.recreate_list then
       local new_menu = {}
       if self.list_array then
-	 local total_count = table.getn(self.list_array) 
-	 local start_num = (self.current_number - 15 > 0) and self.current_number - 15 or 1
-	 local end_num = (self.current_number + 15 < total_count ) and self.current_number + 15 or total_count
-	 for i = start_num, end_num do
+         local total_count = table.getn(self.list_array) 
+         local start_num = (self.current_number - 15 > 0) and self.current_number - 15 or 1
+         local end_num = (self.current_number + 15 < total_count ) and self.current_number + 15 or total_count
+         for i = start_num, end_num do
             table.insert(new_menu, { jamendo.replace_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)
                                      or nil} )
-	 end
+         end
       end
       self.recreate_list = false
       self.list_menu = new_menu
@@ -524,6 +539,27 @@ function awesompd:menu_jamendo_format()
    return self.jamendo_formats_menu
 end
 
+function awesompd:menu_jamendo_browse()
+   if self.recreate_jamendo_browse and self.browser then
+      local track = jamendo.get_track_by_link(self.unique_text)
+      local new_menu
+      if track then
+         local artist_link = 
+            "http://www.jamendo.com/artist/" .. track.artist_link_name
+         local album_link =
+            "http://www.jamendo.com/album/" .. track.album_id
+         new_menu = { { "Artist's page" , 
+                        self:command_open_in_browser(artist_link) },
+                      { "Album's page" ,
+                        self:command_open_in_browser(album_link) } }
+         self.jamendo_browse_menu = { "Browse on Jamendo", new_menu }
+      else
+         self.jamendo_browse_menu = nil
+      end
+   end
+   return self.jamendo_browse_menu
+end
+
 function awesompd:menu_jamendo_order()
    if self.recreate_jamendo_order then
       local setorder =
@@ -946,5 +982,5 @@ end
 -- configuration ///
 
 function awesompd:command_toggle()
-   self:command_playpause()
+   return self:command_playpause()
 end
diff --git a/jamendo.lua b/jamendo.lua
index 78dc962..9104ac3 100644
--- a/jamendo.lua
+++ b/jamendo.lua
@@ -58,7 +58,7 @@ ALL_ORDERS = { ORDER_RELEVANCE, ORDER_RANDOM, ORDER_RATINGDAILY,
                ORDER_RATINGWEEKLY, ORDER_RATINGTOTAL }
 
 current_request_table = { unit = "track", 
-                          fields = {"id", "artist_name", "name", 
+                          fields = {"id", "artist_url", "artist_name", "name", 
                                     "stream", "album_image" },
                           joins = { "track_album", "album_artist" },
                           params = { streamencoding = FORMAT_MP3, 
@@ -68,6 +68,7 @@ current_request_table = { unit = "track",
 -- Local variables
 local jamendo_list = {}
 local cache_file = awful.util.getdir ("cache").."/jamendo_cache"
+local cache_header = "[version=1.0.6]"
 local album_covers_folder = awful.util.getdir("cache") .. "/jamendo_covers/"
 local default_mp3_stream = nil
 local search_template = { fields = { "id", "name" },
@@ -90,9 +91,21 @@ function get_default_mp3_stream()
    return default_mp3_stream.id
 end
 
--- Returns the track ID from the given link to Jamendo stream.
-function get_id_from_link(link)
+-- Returns the track ID from the given link to Jamendo stream.  MPD
+-- transforms Ogg stream links into normal track names. Good for it
+-- but bad for us! We don't know if the song is streamed from Jamendo
+-- anymore. The best we can do is to look through the whole
+-- jamendo_list and compare it with the given track name. If
+-- scan_for_song_name is not nil, then we will perform this check.
+function get_id_from_link(link, scan_for_song_name)
    local _, _, id = string.find(link,"stream/(%d+)")
+   if not id and scan_for_song_name then
+      for _, track in pairs(jamendo_list) do
+         if track.display_name == link then
+            return track.id
+         end
+      end
+   end
    return id
 end
 
@@ -113,6 +126,22 @@ function get_name_by_link(link)
    end
 end
 
+-- Returns the album id for given music stream.
+function get_album_id_by_link(link)
+   local id = get_id_from_link(link, true)
+   if id and jamendo_list[id] then
+      return jamendo_list[id].album_id
+   end
+end
+
+-- Returns the track table for the given music stream.
+function get_track_by_link(link)
+   local id = get_id_from_link(link, true)
+   if id and jamendo_list[id] then
+      return jamendo_list[id]
+   end
+end
+
 -- If a track is actually a Jamendo stream, replace it with normal
 -- track name.
 function replace_link(track)
@@ -136,6 +165,8 @@ function return_track_table(request_table)
          -- 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].artist_link_name = 
+         string.find(parse_table[i].artist_url, "jamendo.com\\/artist\\/(.+)")
       parse_table[i].display_name = 
          parse_table[i].artist_name .. " - " .. parse_table[i].name
       -- Do Jamendo a favor, extract album_id for the track yourself
@@ -303,14 +334,22 @@ function retrieve_cache()
    local bus = io.open(cache_file)
    local track = {}
    if bus then
-      for l in bus:lines() do
-         local _, _, id, album_id, track_name = 
-            string.find(l,"(%d+)-(%d+)-(.+)")
-         track = {}
-         track.id = id
-         track.album_id = album_id
-         track.display_name = track_name
-         jamendo_list[id] = track
+      local header = bus:read("*line")
+      if header == cache_header then 
+         for l in bus:lines() do
+            local _, _, id, artist_link_name, album_id, track_name = 
+               string.find(l,"(%d+)-([^-]+)-(%d+)-(.+)")
+            track = {}
+            track.id = id
+            track.artist_link_name = artist_link_name
+            track.album_id = album_id
+            track.display_name = track_name
+            jamendo_list[id] = track
+         end
+      else 
+         -- We encountered an outdated version of the cache
+         -- file. Let's just remove it.
+         awful.util.spawn("rm -f " .. cache_file)
       end
    end
 end
@@ -319,8 +358,9 @@ end
 -- file.
 function save_cache()
    local bus = io.open(cache_file, "w")
+   bus:write(cache_header .. "\n")
    for id,track in pairs(jamendo_list) do
-      bus:write(string.format("%s-%s-%s\n", id, 
+      bus:write(string.format("%s-%s-%s-%s\n", id, track.artist_link_name,
                               track.album_id, track.display_name))
    end
    bus:flush()
@@ -374,22 +414,9 @@ end
 -- Checks if track_name is actually a link to Jamendo stream. If true
 -- returns the file with album cover for the track.
 function try_get_cover(track_name)
-   if string.find(track_name, "jamendo.com/stream") then
-      return get_album_cover(get_id_from_link(track_name))
-   else
-      -- MPD transforms Ogg stream links into normal track names. Good
-      -- for it but bad for us! We don't know if the song is streamed
-      -- from Jamendo anymore. The best we can do for now is to look
-      -- through the whole jamendo_list and compare it with the given
-      -- track name.
-      for _, track in pairs(jamendo_list) do
-         if track.display_name == track_name then
-            return get_album_cover(track.id)
-         end
-      end
-      -- Seems like it is not a Jamendo stream. And even if it is, we
-      -- still can't do anything.
-      return nil
+   local id = get_id_from_link(track_name, true)
+   if id then 
+      return get_album_cover(id)
    end
 end
 
diff --git a/rcsample.lua b/rcsample.lua
index 336f2ef..6a54f4a 100644
--- a/rcsample.lua
+++ b/rcsample.lua
@@ -96,6 +96,10 @@ mysystray = widget({ type = "systray" })
   -- this option on the fly in awesompd itself.
   -- possible formats: awesompd.FORMAT_MP3, awesompd.FORMAT_OGG
   musicwidget.jamendo_format = awesompd.FORMAT_MP3
+  
+  -- Specify the browser you use so awesompd can open links from
+  -- Jamendo in it.
+  musicwidget.browser = "firefox"
 
   -- If true, song notifications for Jamendo tracks and local tracks
   -- will also contain album cover image.
-- 
cgit v1.2.3