Class: Muzak::Index

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/muzak/index.rb

Overview

Represents muzak's music index.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utils

#album_art?, #debug, #debug?, #error, #fail_arity, #info, #music?, #output, #pretty, resolve_command, resolve_method, #verbose, #verbose?, #warn, #warn_arity

Constructor Details

#initialize(tree, deep: false) ⇒ Index

Note:

if the index (Muzak::INDEX_FILE) already exists and is not outdated, no building is performed.

Returns a new instance of Index.

Parameters:

  • tree (String)

    the root to begin indexing from

  • deep (Boolean) (defaults to: false)

    whether to build a "deep" index

See Also:



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/muzak/index.rb', line 20

def initialize(tree, deep: false)
  @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!
end

Instance Attribute Details

#deepBoolean

Returns whether the index is "deep" (includes metadata) or not.

Returns:

  • (Boolean)

    whether the index is "deep" (includes metadata) or not



10
11
12
# File 'lib/muzak/index.rb', line 10

def deep
  @deep
end

#hashHash

Returns the index hash.

Returns:

  • (Hash)

    the index hash



13
14
15
# File 'lib/muzak/index.rb', line 13

def hash
  @hash
end

#treeString

Returns the path of the root of the music tree.

Returns:

  • (String)

    the path of the root of the music tree



7
8
9
# File 'lib/muzak/index.rb', line 7

def tree
  @tree
end

Instance Method Details

#album_namesArray<String>

Note:

albums with the same name will appear, but can't be disambiguated from here

Returns a list of all albums in the index.

Returns:

  • (Array<String>)

    a list of all albums in the index



84
85
86
# File 'lib/muzak/index.rb', line 84

def album_names
  artists.map { |a| @hash["artists"][a]["albums"].keys }.flatten
end

#albumsHash{String => Album}

Returns a hash of all album names with their Album objects.

Returns:

  • (Hash{String => Album})

    a hash of all album names with their Album objects



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/muzak/index.rb', line 67

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.

Parameters:

  • artist (String)

    the artist's name

Returns:

  • (Array<Album>)

    all albums by the given artist



90
91
92
93
94
95
96
97
# File 'lib/muzak/index.rb', line 90

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

#artistsArray<String>

Returns a list of all artists in the index.

Returns:

  • (Array<String>)

    a list of all artists in the index



61
62
63
# File 'lib/muzak/index.rb', line 61

def artists
  @artists ||= @hash["artists"].keys
end

#build!Object

Note:

This method can be expensive.

(Re)builds and saves the index (Muzak::INDEX_FILE) to disk.



35
36
37
38
39
40
41
# File 'lib/muzak/index.rb', line 35

def build!
  @hash = build_index_hash!

  debug "indexed #{albums.length} albums by #{artists.length} artists"

  File.open(INDEX_FILE, "w") { |io| io.write Marshal::dump @hash }
end

#deep?Boolean

Returns whether or not the current index is deep.

Returns:

  • (Boolean)

    whether or not the current index is deep



44
45
46
# File 'lib/muzak/index.rb', line 44

def deep?
  deep
end

#jukebox(count = 50) ⇒ Array<Song>

Produces a 'jukebox' of random songs.

Parameters:

  • count (Integer) (defaults to: 50)

    the number of random songs to return

Returns:

  • (Array<Song>)

    an array of randomly chosen songs



102
103
104
105
106
107
108
109
110
111
112
# File 'lib/muzak/index.rb', line 102

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

Note:

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.

Returns:

  • (Boolean)

    whether or not the index is currently out of date



56
57
58
# File 'lib/muzak/index.rb', line 56

def outdated?
  Time.now.to_i - timestamp >= Config.index_autobuild
end

#songs_by(artist) ⇒ Array<Song>

Note:

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.

Parameters:

  • artist (String)

    the artist's name

Returns:

  • (Array<Song>)

    an array of all the artist's songs



118
119
120
121
122
123
124
125
126
127
128
# File 'lib/muzak/index.rb', line 118

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

#timestampInteger

Returns the UNIX timestamp from when the index was built.

Returns:

  • (Integer)

    the UNIX timestamp from when the index was built



49
50
51
# File 'lib/muzak/index.rb', line 49

def timestamp
  @hash["timestamp"]
end