=begin AUTHOR: Kesiev WHAT IT DOES: Adds a simple Magnatune store frontend. The Magnatune database is downloaded and searched using a simple interface. Adds contextual options into the Magnatune search results for searching album and/or artist into the database and menus for querying the database or go to the Magnatune homepage. Visit the related link for current playng song or into the contextual menu for purchasing album. You can purchase an album also from the song menu. "Remember to buy!" advertising after a bunch of seconds of playback. You can disable these notificatons (is unfair!) adding to the :opt: section :hidemagnatunenotifies: true This plugin could be much better but is a great sample of simple integration. =end # Playlist entry $lists << { :label=> "Magnatune store", :icon=> "file:#{$opt[:root]}/magnatuneicon", :file=>"#{$opt[:root]}/magnatune", :magnatunedb=>"#{$opt[:root]}/magnatunedb", :protected=>true, :onclick=>Proc.new { |l| if !File.exist?(l[:magnatunedb]) then Thread.new { magnatune_downloaddb(l) } end; :update }, :onrefresh=>Proc.new {|l| magnatune_downloaddb(l)}, :onrefreshask=> "Update the Magnatune database?" } # Background download of the Magnatune favicon as the entry icon if !File.exist?("#{$opt[:root]}/magnatuneicon") then Thread.new { open("http://www.magnatune.com/favicon.ico","r") { |fin| open("#{$opt[:root]}/magnatuneicon", "w") { |fout| while (buf = fin.read(8192)) do fout.write buf end } } updatemodes } end # Get the first magnatune list item def magnatune_get $lists.each { |item| if (item[:magnatunedb]) then return item end } return nil end # Adding the magnatune menu before the Help menu $menulist.insert($menulist.length-1, { :label => "Magnatune", :id=>:magnatune, :showif=>Proc.new {|s| s[:magnatunedb]} }) # Adding menu items for searching, going to the magnatune home and purchase # the now played song. $menus <<{ :menu=>:magnatune, :label=>"Search...", :action=>Proc.new{ magnatune_form } }<<{ :menu=>:magnatune, :label=>"Magnatune homepage", :action=>Proc.new{ surf("http://www.magnatune.com/") } }<<{ :menu=>:song, :label=>"Purchase on Magnatune", :action=>Proc.new { if $player.meta[:custommeta].to_s[0..13]=="magnatuneshop:" then surf($player.meta[:custommeta][14..-1]) else $statbar.push($statbar.get_context_id("relatedurl"),"Sorry, \"#{$player.meta[:title]}\" is not from Magnatune.") end } } # Adding contextual actions for magnatune searches $contextactions << { :label => "Purchase on Magnatune", :verifyer => Proc.new{ |s| s[COLMAP[:custommeta]].to_s[0..13]=="magnatuneshop:"}, :action => Proc.new{ |s| surf(s[COLMAP[:custommeta]][14..-1]) } } << { :label => "Search Magnatune for artist", :verifyer => Proc.new{ |s| s[COLMAP[:custommeta]].to_s[0..13]=="magnatuneshop:"}, :action => Proc.new{ |s| magnatune_search(magnatune_get,s[COLMAP[:artist]]);setmode(magnatune_get) } } << { :label => "Search Magnatune for album", :verifyer => Proc.new{ |s| s[COLMAP[:custommeta]].to_s[0..13]=="magnatuneshop:"}, :action => Proc.new{ |s| magnatune_search(magnatune_get,s[COLMAP[:album]]); setmode(magnatune_get) } } # downloads the magnatune database $magnatune_downloading=false; def magnatune_downloaddb(section) # ensure a download at time if !$magnatune_downloading $magnatune_downloading=true $statbar.push($statbar.get_context_id("magnatune"),"Downloading magnatune database...") # download with another name open("http://www.magnatune.com/info/song_info.csv","r") { |fin| open(section[:magnatunedb]+"_partial", "w") { |fout| while (buf = fin.read(8192)) do fout.write buf end } } # and rename it once downloaded File.rename(section[:magnatunedb]+"_partial",section[:magnatunedb]) $statbar.push($statbar.get_context_id("magnatune"),"Magnatune database downloaded.") $magnatune_downloading=false else $statbar.push($statbar.get_context_id("magnatune"),"Downloading magnatune database... Please wait.") end end # searches the local Magnatune database and creates the local playlist def magnatune_search(section,query) query.downcase! open(section[:file],"w") { |f| open(section[:magnatunedb],"r").each { |line| entry=line.split("\",\"") if (entry[0]+" "+entry[1]+" "+entry[2]+" "+entry[3]+" "+entry[4]+" "+entry[5]+" "+entry[6]).downcase.index(query) then f.puts(formatrecord({:year=>entry[4],:artist=>entry[0][1..-1], :album=>entry[2], :trackno=>entry[3], :title=>entry[1], :url=>entry[10], :file=>entry[8], :cover=>entry[12], :custommeta=>"magnatuneshop:"+entry[9]})); end } } setmode(section) end # "Remember to buy" message when a Magnatune song is played alias magnatune_play play def play(iter) if iter[COLMAP[:url]].to_s[/magnatune.com/] then Thread.new { sleep 30 if $player.meta[:url].to_s[/magnatune.com/] then if $notifies && !$opt[:hidemagnatunenotifies] then Notify::Notification.new($window.title,"Remember to buy \""+$player.meta[:title]+"\" on Magnatune!",nil,$tray).show else $statbar.push($statbar.get_context_id("magnatune"),"Remember to buy \""+$player.meta[:title]+"\" on Magnatune!") end end } end magnatune_play(iter) end # searches the first magnatune store entry def magnatune_form section=magnatune_get # if database is unavailable, downloads it if !File.exist?(section[:magnatunedb]) Thread.new { magnatune_downloaddb(section) } else # opens the search box searchbox = Gtk::Window.new searchbox.modal=true searchbox.title="Search Magnatune store" searchbox.border_width = 5 searchbox.set_default_size(400,30) searchbox.add(mbox=Gtk::HBox.new) mbox.spacing=5 mbox.pack_start(Gtk::Label.new("Search in Magnatune"),false,false) mbox.pack_start(editbox=Gtk::Entry.new,true,true) mbox.pack_start(confirm=Gtk::Button.new("Search"),false,true) mbox.pack_start(cancel=Gtk::Button.new("Cancel"),false,true) confirm.signal_connect("clicked") { magnatune_search(section,editbox.text) searchbox.destroy } editbox.signal_connect("activate") { magnatune_search(section,editbox.text) searchbox.destroy } cancel.signal_connect("clicked") { searchbox.destroy } searchbox.show_all end end