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

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

album_art?, #build_response, #danger, #debug, #debug?, #error, #error!, music?, #output, #pretty, #verbose, #verbose?, which?

Constructor Details

#initialize(file: Config::INDEX_FILE) ⇒ Index

Returns a new instance of Index.

Parameters:

  • file (String) (defaults to: Config::INDEX_FILE)

    the path of the index data file



25
26
27
28
29
30
31
32
33
# File 'lib/muzak/index.rb', line 25

def initialize(file: Config::INDEX_FILE)
  debug "loading index from '#{file}'..."

  @file = file

  @hash = Marshal.load(File.read file)

  memoize_collections!
end

Instance Attribute Details

#fileString

Returns the path of the index data file.

Returns:

  • (String)

    the path of the index data file



16
17
18
# File 'lib/muzak/index.rb', line 16

def file
  @file
end

#hashHash

Returns the index hash.

Returns:

  • (Hash)

    the index hash



22
23
24
# File 'lib/muzak/index.rb', line 22

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



19
20
21
# File 'lib/muzak/index.rb', line 19

def tree
  @tree
end

Class Method Details

.load_index!Index

Returns a Muzak::Index instance instantiated with Config::INDEX_FILE.

Returns:



7
8
9
10
11
12
13
# File 'lib/muzak/index.rb', line 7

def self.load_index!
  if File.exist?(Config::INDEX_FILE)
    Index.new
  else
    error! "#{Config::INDEX_FILE} missing, did you forget to run muzak-index?"
  end
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



94
95
96
# File 'lib/muzak/index.rb', line 94

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



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/muzak/index.rb', line 61

def albums
  @albums_hash ||= begin
    albums_hash = {}

    artists.each do |a|
      @hash["artists"][a]["albums"].each do |title, album_hash|
        if deep?
          songs = album_hash["deep-songs"]
        else
          songs = album_hash["songs"].map { |s| Song.new(s) }
        end
        albums_hash[title] = Album.new(title, songs, album_hash["cover"])
      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



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

def albums_by(artist)
  if artists.include?(artist)
    @hash["artists"][artist]["albums"].map do |title, album_hash|
      if deep?
        songs = album_hash["deep-songs"]
      else
        songs = album_hash["songs"].map { |s| Song.new(s) }
      end
      Album.new(title, songs, album_hash["cover"])
    end
  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



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

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

#deep?Boolean

Returns whether or not the current index is deep.

Returns:

  • (Boolean)

    whether or not the current index is deep



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

def deep?
  @hash["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



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

def jukebox(count = 50)
  if deep?
    @all_deep_songs.sample(count)
  else
    @all_songs.sample(count).map { |s| Song.new(s) }
  end
end

#memoize_collections!void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Create some frequently accessed collections to speed things up a bit.



146
147
148
149
150
151
152
153
154
# File 'lib/muzak/index.rb', line 146

def memoize_collections!
  @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
  else
    @all_songs = @all_albums.map { |aa| aa.map { |_, a| a["songs"] } }.flatten
  end
end

#reload!void

Note:

This method does not rebuild the index data file.

This method returns an undefined value.

Refresh the Muzak::Index instance's state from the index data file.



38
39
40
41
42
# File 'lib/muzak/index.rb', line 38

def reload!
  debug "reloading index from '#{file}'..."
  @hash = Marshal.load(File.read file)
  memoize_collections!
end

#songsArray<Song>

Note:

This method requires a deep index.

Returns a list of all Song objects in the index.

Returns:

  • (Array<Song>)

    a list of all Song objects in the index



82
83
84
85
86
87
88
89
# File 'lib/muzak/index.rb', line 82

def songs
  unless deep?
    danger "tried to call a deep-index-only method with a shallow index"
    return []
  end

  @all_deep_songs
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



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/muzak/index.rb', line 131

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



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

def timestamp
  @hash["timestamp"]
end