Class: Muzak::Index
Overview
Represents muzak's music index.
Instance Attribute Summary collapse
-
#deep ⇒ Boolean
Whether the index is "deep" (includes metadata) or not.
-
#hash ⇒ Hash
The index hash.
-
#tree ⇒ String
The path of the root of the music tree.
Class Method Summary collapse
Instance Method Summary collapse
-
#album_names ⇒ Array<String>
A list of all albums in the index.
-
#albums ⇒ Hash{String => Album}
A hash of all album names with their Album objects.
-
#albums_by(artist) ⇒ Array<Album>
All albums by the given artist.
-
#artists ⇒ Array<String>
A list of all artists in the index.
-
#build!(sync: true) ⇒ Object
(Re)builds and saves the index (INDEX_FILE) to disk.
-
#deep? ⇒ Boolean
Whether or not the current index is deep.
-
#initialize(tree, deep: false, sync: true) ⇒ Index
constructor
A new instance of Index.
-
#jukebox(count = 50) ⇒ Array<Song>
Produces a 'jukebox' of random songs.
-
#outdated? ⇒ Boolean
Whether or not the index is currently out of date.
-
#songs_by(artist) ⇒ Array<Song>
An array of all the artist's songs.
-
#sync! ⇒ Object
Synchronize the in-memory index hash with INDEX_FILE.
-
#timestamp ⇒ Integer
The UNIX timestamp from when the index was built.
Methods included from Utils
#album_art?, #build_response, #debug, #debug?, #error, #error!, #music?, #output, #pretty, resolve_command, resolve_method, #verbose, #verbose?, #warn
Constructor Details
#initialize(tree, deep: false, sync: true) ⇒ Index
if the index (Muzak::INDEX_FILE) already exists and is not outdated, no building is performed.
Returns a new instance of Index.
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/muzak/index.rb', line 25 def initialize(tree, deep: false, sync: true) @tree = tree @deep = deep if File.exist?(INDEX_FILE) verbose "loading index from #{INDEX_FILE}" @hash = Marshal::load(File.read INDEX_FILE) return unless outdated? end build!(sync) end |
Instance Attribute Details
#deep ⇒ Boolean
Returns whether the index is "deep" (includes metadata) or not.
14 15 16 |
# File 'lib/muzak/index.rb', line 14 def deep @deep end |
#hash ⇒ Hash
Returns the index hash.
17 18 19 |
# File 'lib/muzak/index.rb', line 17 def hash @hash end |
#tree ⇒ String
Returns the path of the root of the music tree.
11 12 13 |
# File 'lib/muzak/index.rb', line 11 def tree @tree end |
Class Method Details
.load_index! ⇒ Object
6 7 8 |
# File 'lib/muzak/index.rb', line 6 def self.load_index! Index.new(Config.music, deep: Config.deep_index) end |
Instance Method Details
#album_names ⇒ Array<String>
albums with the same name will appear, but can't be disambiguated from here
Returns a list of all albums in the index.
96 97 98 |
# File 'lib/muzak/index.rb', line 96 def album_names artists.map { |a| @hash["artists"][a]["albums"].keys }.flatten end |
#albums ⇒ Hash{String => Album}
Returns a hash of all album names with their Album objects.
79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/muzak/index.rb', line 79 def albums @albums_hash ||= begin albums_hash = {} artists.each do |a| @hash["artists"][a]["albums"].each do |title, album_hash| albums_hash[title] = Album.new(title, album_hash) end end albums_hash end end |
#albums_by(artist) ⇒ Array<Album>
Returns all albums by the given artist.
102 103 104 105 106 107 108 109 |
# File 'lib/muzak/index.rb', line 102 def albums_by(artist) if artists.include?(artist) @hash["artists"][artist]["albums"].map { |title, album| Album.new(title, album) } else error "no such artist: '#{artist}'" unless @hash["artists"].key?(artist) [] end end |
#artists ⇒ Array<String>
Returns a list of all artists in the index.
73 74 75 |
# File 'lib/muzak/index.rb', line 73 def artists @artists ||= @hash["artists"].keys end |
#build!(sync: true) ⇒ Object
This method can be expensive.
(Re)builds and saves the index (Muzak::INDEX_FILE) to disk.
46 47 48 49 50 51 52 |
# File 'lib/muzak/index.rb', line 46 def build!(sync: true) @hash = build_index_hash! debug "indexed #{albums.length} albums by #{artists.length} artists" sync! if sync end |
#deep? ⇒ Boolean
Returns whether or not the current index is deep.
55 56 57 |
# File 'lib/muzak/index.rb', line 55 def deep? deep end |
#jukebox(count = 50) ⇒ Array<Song>
Produces a 'jukebox' of random songs.
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/muzak/index.rb', line 114 def jukebox(count = 50) @all_albums ||= @hash["artists"].map { |_, a| a["albums"] }.flatten if deep? @all_deep_songs ||= @all_albums.map { |aa| aa.map { |_, a| a["deep-songs"] } }.flatten @all_deep_songs.sample(count) else @all_songs ||= @all_albums.map { |aa| aa.map { |_, a| a["songs"] } }.flatten @all_songs.sample(count).map { |s| Song.new(s) } end end |
#outdated? ⇒ Boolean
The behavior of this method is affected by the value of Config.index_autobuild.
Returns whether or not the index is currently out of date.
67 68 69 70 |
# File 'lib/muzak/index.rb', line 67 def outdated? return false unless Config.index_autobuild Time.now.to_i - >= Config.index_autobuild end |
#songs_by(artist) ⇒ Array<Song>
no inter-album order is guaranteed. songs within an album are generally sorted by track number.
Returns an array of all the artist's songs.
130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/muzak/index.rb', line 130 def songs_by(artist) error "no such artist: '#{artist}'" unless @hash["artists"].key?(artist) begin albums_by(artist).map do |album| album.songs end.flatten rescue Exception => e [] end end |
#sync! ⇒ Object
Synchronize the in-memory index hash with Muzak::INDEX_FILE.
39 40 41 |
# File 'lib/muzak/index.rb', line 39 def sync! File.open(INDEX_FILE, "w") { |io| io.write Marshal::dump @hash } end |
#timestamp ⇒ Integer
Returns the UNIX timestamp from when the index was built.
60 61 62 |
# File 'lib/muzak/index.rb', line 60 def @hash["timestamp"] end |