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


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

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

  @file = file
  @hash = Marshal.load File.read(file) # rubocop:disable Security/MarshalLoad

  memoize_collections!
end

Instance Attribute Details

#fileString

Returns the path of the index data file.

Returns:

  • (String)

    the path of the index data file


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

def file
  @file
end

#hashHash

Returns the index hash.

Returns:

  • (Hash)

    the index hash


24
25
26
# File 'lib/muzak/index.rb', line 24

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


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

def tree
  @tree
end

Class Method Details

.load_index!Index

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

Returns:


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

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


92
93
94
# File 'lib/muzak/index.rb', line 92

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


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

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

    artists.each do |a|
      @hash["artists"][a]["albums"].each do |title, album_hash|
        songs = load_songs album_hash
        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


98
99
100
101
102
103
104
105
106
107
108
# File 'lib/muzak/index.rb', line 98

def albums_by(artist)
  if artists.include?(artist)
    @hash["artists"][artist]["albums"].map do |title, album_hash|
      songs = load_songs album_hash
      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


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

def 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


47
48
49
# File 'lib/muzak/index.rb', line 47

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


113
114
115
116
117
118
119
# File 'lib/muzak/index.rb', line 113

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

#load_songs(ah) ⇒ Object

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.

Load the songs from an album hash into Song instances.

Parameters:

  • ah (Hash)

    the album hash


153
154
155
156
157
158
159
# File 'lib/muzak/index.rb', line 153

def load_songs(ah)
  if deep?
    ah["deep-songs"]
  else
    ah["songs"].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.


138
139
140
141
142
143
144
145
146
147
148
# File 'lib/muzak/index.rb', line 138

def memoize_collections!
  @all_albums = @hash["artists"].map { |_, a| a["albums"] }.flatten

  if deep?
    @all_deep_songs = @all_albums.map do |aa|
      aa.map { |_, a| a["deep-songs"] }
    end.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.


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

def reload!
  debug "reloading index from '#{file}'..."
  @hash = Marshal.load File.read(file) # rubocop:disable Security/MarshalLoad
  @albums_hash = nil
  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


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

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


125
126
127
128
129
130
131
132
133
# File 'lib/muzak/index.rb', line 125

def songs_by(artist)
  error "no such artist: '#{artist}'" unless @hash["artists"].key?(artist)

  begin
    albums_by(artist).map(&:songs).flatten
  rescue
    []
  end
end

#timestampInteger

Returns the UNIX timestamp from when the index was built.

Returns:

  • (Integer)

    the UNIX timestamp from when the index was built


52
53
54
# File 'lib/muzak/index.rb', line 52

def timestamp
  @hash["timestamp"]
end