muzak 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/lib/muzak/album.rb +11 -4
- data/lib/muzak/cmd.rb +1 -0
- data/lib/muzak/cmd/config.rb +3 -0
- data/lib/muzak/cmd/index.rb +15 -0
- data/lib/muzak/cmd/meta.rb +11 -0
- data/lib/muzak/cmd/player.rb +45 -0
- data/lib/muzak/cmd/playlist.rb +29 -13
- data/lib/muzak/config.rb +11 -1
- data/lib/muzak/const.rb +16 -1
- data/lib/muzak/index.rb +37 -1
- data/lib/muzak/instance.rb +23 -2
- data/lib/muzak/player.rb +9 -1
- data/lib/muzak/player/mpv.rb +42 -0
- data/lib/muzak/player/stub_player.rb +51 -0
- data/lib/muzak/playlist.rb +34 -1
- data/lib/muzak/plugin.rb +8 -1
- data/lib/muzak/plugin/stub_plugin.rb +4 -4
- data/lib/muzak/song.rb +36 -1
- data/lib/muzak/utils.rb +52 -0
- metadata +4 -6
- data/lib/muzak/plugin/cava.rb +0 -44
- data/lib/muzak/plugin/notify.rb +0 -16
- data/lib/muzak/plugin/scrobble.rb +0 -81
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdbf4e0b472fdf7499bbd25915c178c00ea427f2
|
4
|
+
data.tar.gz: e0b39265673163d195dde538960beb7819e2ebbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18ae7d00640668f375390afc84d2ec0aec1fde26970d9e1636c943a7a29415267b97cf5c433efc2967ad630726525f617493a77e30cc2072646af95406078de1
|
7
|
+
data.tar.gz: 51f3a12b1e2018fb52c118cbd79afdc47a22a9a0a7feaf724960baffc9604b77042aafd60d3b0e7117e8b37bd9c12475c0653ffc71befc722c43c3289229b5f6
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--tag command:"muzak command" --tag cmdexample:"example invocation" --no-private --markup-provider=redcarpet --markup=markdown - README.md LICENSE
|
data/lib/muzak/album.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
module Muzak
|
2
|
+
# Represents a collection of songs for muzak.
|
2
3
|
class Album
|
3
|
-
|
4
|
+
# @return [String] the album's title
|
5
|
+
attr_reader :title
|
4
6
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
7
|
+
# @return [Array<Muzak::Song>] the album's songs
|
8
|
+
attr_reader :songs
|
9
|
+
|
10
|
+
# @return [String] the path to the album's cover art
|
11
|
+
attr_reader :cover_art
|
12
|
+
|
13
|
+
# @note instead of passing an album hash directly from the index, this
|
14
|
+
# should really just take a title and an array of Song objects.
|
8
15
|
def initialize(title, album_hash)
|
9
16
|
@title = title
|
10
17
|
@cover_art = album_hash["cover"]
|
data/lib/muzak/cmd.rb
CHANGED
@@ -5,6 +5,7 @@ module Muzak
|
|
5
5
|
# load commands included by the user
|
6
6
|
Dir.glob(File.join(USER_COMMAND_DIR, "*")) { |file| require file }
|
7
7
|
|
8
|
+
# @return [Array<String>] all valid muzak commands
|
8
9
|
def self.commands
|
9
10
|
commands = instance_methods.map(&:to_s).reject { |m| m.start_with?("_") }
|
10
11
|
commands.map { |c| Utils.resolve_method c }
|
data/lib/muzak/cmd/config.rb
CHANGED
data/lib/muzak/cmd/index.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Muzak
|
2
2
|
module Cmd
|
3
|
+
# Rebuild the current instance's index.
|
4
|
+
# @command `index-build`
|
5
|
+
# @cmdexample `muzak> index-build`
|
3
6
|
def index_build(*args)
|
4
7
|
warn_arity(args, 0)
|
5
8
|
|
@@ -8,18 +11,27 @@ module Muzak
|
|
8
11
|
index.build!
|
9
12
|
end
|
10
13
|
|
14
|
+
# List all artists in the index.
|
15
|
+
# @command `list-artists`
|
16
|
+
# @cmdexample `muzak> list-artists`
|
11
17
|
def list_artists(*args)
|
12
18
|
warn_arity(args, 0)
|
13
19
|
|
14
20
|
puts index.artists.join("\n")
|
15
21
|
end
|
16
22
|
|
23
|
+
# List all albums in the index.
|
24
|
+
# @command `list-albums`
|
25
|
+
# @cmdexample `muzak> list-albums`
|
17
26
|
def list_albums(*args)
|
18
27
|
warn_arity(args, 0)
|
19
28
|
|
20
29
|
puts index.album_names.join("\n")
|
21
30
|
end
|
22
31
|
|
32
|
+
# List all albums by the given artist in the index.
|
33
|
+
# @command `albums-by-artist <artist name>`
|
34
|
+
# @cmdexample `muzak> albums-by-artist Your Favorite Artist`
|
23
35
|
def albums_by_artist(*args)
|
24
36
|
artist = args.join(" ")
|
25
37
|
return if artist.nil?
|
@@ -27,6 +39,9 @@ module Muzak
|
|
27
39
|
puts index.albums_by(artist).map(&:title)
|
28
40
|
end
|
29
41
|
|
42
|
+
# List all songs by the given artist in the index.
|
43
|
+
# @command `songs-by-artist <artist name>`
|
44
|
+
# @cmdexample `muzak> songs-by-artist Your Next Favorite Artist`
|
30
45
|
def songs_by_artist(*args)
|
31
46
|
artist = args.join(" ")
|
32
47
|
return if artist.nil?
|
data/lib/muzak/cmd/meta.rb
CHANGED
@@ -1,15 +1,26 @@
|
|
1
1
|
module Muzak
|
2
2
|
module Cmd
|
3
|
+
# Print a "helpful" listing of commands.
|
4
|
+
# @command `help`
|
5
|
+
# @cmdexample `muzak> help`
|
3
6
|
def help(*args)
|
4
7
|
commands = Muzak::Cmd.commands.join(", ")
|
5
8
|
info "available commands: #{commands}"
|
6
9
|
end
|
7
10
|
|
11
|
+
# List all available plugins.
|
12
|
+
# @command `list-plugins`
|
13
|
+
# @cmdexample `muzak> list-plugins`
|
14
|
+
# @note This list will differ from loaded plugins, if not all available
|
15
|
+
# plugins are configured.
|
8
16
|
def list_plugins
|
9
17
|
plugins = Plugin.plugin_names.join(", ")
|
10
18
|
puts "available plugins: #{plugins}"
|
11
19
|
end
|
12
20
|
|
21
|
+
# Terminates the muzak instance (**not** just the client).
|
22
|
+
# @command `quit`
|
23
|
+
# @cmdexample `muzak> quit`
|
13
24
|
def quit
|
14
25
|
verbose "muzak is quitting..."
|
15
26
|
player.deactivate!
|
data/lib/muzak/cmd/player.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
module Muzak
|
2
2
|
module Cmd
|
3
|
+
# Activate the configured player.
|
4
|
+
# @command `player-activate`
|
5
|
+
# @cmdexample `muzak> player-activate`
|
6
|
+
# @note Many playback commands will automatically activate the player.
|
3
7
|
def player_activate
|
4
8
|
if player.running?
|
5
9
|
warn "player is already running"
|
@@ -9,6 +13,10 @@ module Muzak
|
|
9
13
|
player.activate!
|
10
14
|
end
|
11
15
|
|
16
|
+
# Deactivate the configured player.
|
17
|
+
# @command `player-deactivate`
|
18
|
+
# @cmdexample `muzak> player-deactivate`
|
19
|
+
# @note Deactivating the player (usually) ends playback immediately.
|
12
20
|
def player_deactivate
|
13
21
|
warn "player is not running" unless player.running?
|
14
22
|
|
@@ -16,14 +24,23 @@ module Muzak
|
|
16
24
|
player.deactivate!
|
17
25
|
end
|
18
26
|
|
27
|
+
# Tell the player to begin playback.
|
28
|
+
# @command `play`
|
29
|
+
# @cmdexample `muzak> play`
|
19
30
|
def play
|
20
31
|
player.play
|
21
32
|
end
|
22
33
|
|
34
|
+
# Tell the player to pause.
|
35
|
+
# @command `pause`
|
36
|
+
# @cmdexample `muzak> pause`
|
23
37
|
def pause
|
24
38
|
player.pause
|
25
39
|
end
|
26
40
|
|
41
|
+
# Tell the player to toggle its playback state.
|
42
|
+
# @command `toggle`
|
43
|
+
# @cmdexample `muzak> toggle`
|
27
44
|
def toggle
|
28
45
|
if player.playing?
|
29
46
|
player.pause
|
@@ -32,14 +49,23 @@ module Muzak
|
|
32
49
|
end
|
33
50
|
end
|
34
51
|
|
52
|
+
# Tell the player to load the next song.
|
53
|
+
# @command `next`
|
54
|
+
# @cmdexample `muzak> next`
|
35
55
|
def next
|
36
56
|
player.next_song
|
37
57
|
end
|
38
58
|
|
59
|
+
# Tell the player to load the previous song.
|
60
|
+
# @command `previous`
|
61
|
+
# @cmdexample `muzak> previous`
|
39
62
|
def previous
|
40
63
|
player.previous_song
|
41
64
|
end
|
42
65
|
|
66
|
+
# Tell the player to enqueue all songs by the given artist.
|
67
|
+
# @command `enqueue-artist <artist name>`
|
68
|
+
# @cmdexample `muzak> enqueue-artist Your Favorite Artist`
|
43
69
|
def enqueue_artist(*args)
|
44
70
|
artist = args.join(" ")
|
45
71
|
return if artist.nil?
|
@@ -52,6 +78,9 @@ module Muzak
|
|
52
78
|
end
|
53
79
|
end
|
54
80
|
|
81
|
+
# Tell the player to enqueue the given album.
|
82
|
+
# @command `enqueue-album <album name>`
|
83
|
+
# @cmdexample `muzak> enqueue-album Your Favorite Album`
|
55
84
|
def enqueue_album(*args)
|
56
85
|
album_name = args.join(" ")
|
57
86
|
return if album_name.nil?
|
@@ -64,6 +93,9 @@ module Muzak
|
|
64
93
|
player.enqueue_album album
|
65
94
|
end
|
66
95
|
|
96
|
+
# Tell the player to load the given number of random songs.
|
97
|
+
# @command `jukebox [count]`
|
98
|
+
# @cmdexample `muzak> jukebox 150`
|
67
99
|
def jukebox(*args)
|
68
100
|
count = args.shift || Config.jukebox_size
|
69
101
|
|
@@ -72,18 +104,31 @@ module Muzak
|
|
72
104
|
songs.each { |s| player.enqueue_song s }
|
73
105
|
end
|
74
106
|
|
107
|
+
# Tell the player to list its internal queue.
|
108
|
+
# @command `list-queue`
|
109
|
+
# @cmdexample `muzak> list-queue`
|
75
110
|
def list_queue
|
76
111
|
puts player.list_queue.map(&:title)
|
77
112
|
end
|
78
113
|
|
114
|
+
# Tell the player to shuffle its internal queue.
|
115
|
+
# @command `shuffle-queue`
|
116
|
+
# @cmdexample `muzak> shuffle-queue`
|
79
117
|
def shuffle_queue
|
80
118
|
player.shuffle_queue
|
81
119
|
end
|
82
120
|
|
121
|
+
# Tell the player to clear its internal queue.
|
122
|
+
# @command `clear-queue`
|
123
|
+
# @cmdexample `muzak> clear-queue`
|
124
|
+
# @note This does not (usually) stop the current song.
|
83
125
|
def clear_queue
|
84
126
|
player.clear_queue
|
85
127
|
end
|
86
128
|
|
129
|
+
# Retrieve the currently playing song from the player and print it.
|
130
|
+
# @command `now-playing`
|
131
|
+
# @cmdexample `muzak> now-playing`
|
87
132
|
def now_playing
|
88
133
|
return unless player.playing?
|
89
134
|
|
data/lib/muzak/cmd/playlist.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
module Muzak
|
2
2
|
module Cmd
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# List all currently available playlists.
|
4
|
+
# @command `list-playlists`
|
5
|
+
# @cmdexample `muzak> list-playlists`
|
7
6
|
def list_playlists(*args)
|
8
7
|
Playlist.playlist_names.each do |playlist|
|
9
8
|
info playlist
|
10
9
|
end
|
11
10
|
end
|
12
11
|
|
12
|
+
# Delete the given playlist.
|
13
|
+
# @command `playlist-delete <playlist>`
|
14
|
+
# @cmdexample `muzak> playlist-delete favorites`
|
13
15
|
def playlist_delete(*args)
|
14
16
|
fail_arity(args, 1)
|
15
17
|
pname = args.shift
|
@@ -20,8 +22,10 @@ module Muzak
|
|
20
22
|
playlists[pname] = nil
|
21
23
|
end
|
22
24
|
|
25
|
+
# Add the given playlist to the player's queue.
|
26
|
+
# @command `enqueue-playlist <playlist>`
|
27
|
+
# @cmdexample `muzak> enqueue-playlist favorites`
|
23
28
|
def enqueue_playlist(*args)
|
24
|
-
return unless _playlists_loaded?
|
25
29
|
fail_arity(args, 1)
|
26
30
|
pname = args.shift
|
27
31
|
|
@@ -29,9 +33,10 @@ module Muzak
|
|
29
33
|
event :playlist_enqueued, playlists[pname]
|
30
34
|
end
|
31
35
|
|
36
|
+
# Add the given album to the given playlist.
|
37
|
+
# @command `playlist-add-album <playlist> <album name>`
|
38
|
+
# @cmdexample `muzak> playlist-add-album favorites Your Favorite Album`
|
32
39
|
def playlist_add_album(*args)
|
33
|
-
return unless _playlists_loaded?
|
34
|
-
|
35
40
|
pname = args.shift
|
36
41
|
return if pname.nil?
|
37
42
|
|
@@ -44,9 +49,10 @@ module Muzak
|
|
44
49
|
playlists[pname].add(album.songs)
|
45
50
|
end
|
46
51
|
|
52
|
+
# Add the given artist to the given playlist.
|
53
|
+
# @command `playlist-add-artist <playlist> <artist name>`
|
54
|
+
# @cmdexample `muzak> playlist-add-artist dad-rock The Rolling Stones`
|
47
55
|
def playlist_add_artist(*args)
|
48
|
-
return unless _playlists_loaded?
|
49
|
-
|
50
56
|
pname = args.shift
|
51
57
|
return if pname.nil?
|
52
58
|
|
@@ -56,8 +62,12 @@ module Muzak
|
|
56
62
|
playlists[pname].add(index.songs_by(artist))
|
57
63
|
end
|
58
64
|
|
65
|
+
# Add the currently playing song to the given playlist.
|
66
|
+
# @see Muzak::Player::StubPlayer#now_playing
|
67
|
+
# @command `playlist-add-current <playlist>`
|
68
|
+
# @cmdexample `muzak> playlist-add-current favorites`
|
59
69
|
def playlist_add_current(*args)
|
60
|
-
return unless player.running?
|
70
|
+
return unless player.running?
|
61
71
|
|
62
72
|
pname = args.shift
|
63
73
|
return if pname.nil?
|
@@ -65,8 +75,12 @@ module Muzak
|
|
65
75
|
playlists[pname].add player.now_playing
|
66
76
|
end
|
67
77
|
|
78
|
+
# Deletes the currently playing song from the given playlist.
|
79
|
+
# @see Muzak::Player::StubPlayer#now_playing
|
80
|
+
# @command `playlist-del-current <playlist>`
|
81
|
+
# @cmdexample `muzak> playlist-del-current favorites`
|
68
82
|
def playlist_del_current(*args)
|
69
|
-
return unless player.running?
|
83
|
+
return unless player.running?
|
70
84
|
|
71
85
|
pname = args.shift
|
72
86
|
return if pname.nil?
|
@@ -74,9 +88,11 @@ module Muzak
|
|
74
88
|
playlists[pname].delete player.now_playing
|
75
89
|
end
|
76
90
|
|
91
|
+
# Shuffle the given playlist.
|
92
|
+
# @see Muzak::Playlist#shuffle!
|
93
|
+
# @command `playlist-shuffle <playlist>`
|
94
|
+
# @cmdexample `muzak> playlist-shuffle dad-rock`
|
77
95
|
def playlist_shuffle(*args)
|
78
|
-
return unless _playlists_loaded?
|
79
|
-
|
80
96
|
pname = args.shift
|
81
97
|
return if pname.nil?
|
82
98
|
|
data/lib/muzak/config.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require "yaml"
|
2
2
|
|
3
3
|
module Muzak
|
4
|
+
# Muzak's static configuration dumping ground.
|
5
|
+
# Key-value pairs are loaded from {CONFIG_FILE} and translated from
|
6
|
+
# kebab-case to snake_case methods.
|
7
|
+
# @example
|
8
|
+
# # corresponds to `art-geometry: 300x300` in configuration
|
9
|
+
# Config.art_geometry # => "300x300"
|
4
10
|
class Config
|
5
11
|
if File.exist?(CONFIG_FILE)
|
6
12
|
@config = YAML::load_file(CONFIG_FILE)
|
@@ -24,11 +30,15 @@ module Muzak
|
|
24
30
|
end
|
25
31
|
end
|
26
32
|
|
27
|
-
#
|
33
|
+
# Catches all undefined configuration keys and defaults them to false.
|
34
|
+
# @return [false]
|
28
35
|
def self.method_missing(method, *args)
|
29
36
|
false
|
30
37
|
end
|
31
38
|
|
39
|
+
# @return [Boolean] whether or not the given plugin is configured
|
40
|
+
# @note the truth-value of this method is used to determine which
|
41
|
+
# plugins should be loaded.
|
32
42
|
def self.plugin?(pname)
|
33
43
|
respond_to? "plugin_#{pname}"
|
34
44
|
end
|
data/lib/muzak/const.rb
CHANGED
@@ -1,17 +1,32 @@
|
|
1
1
|
module Muzak
|
2
|
-
|
2
|
+
# Muzak's current version
|
3
|
+
VERSION = "0.0.12".freeze
|
3
4
|
|
5
|
+
# The root directory for all user configuration, data, etc
|
4
6
|
CONFIG_DIR = File.expand_path("~/.config/muzak").freeze
|
7
|
+
|
8
|
+
# Muzak's primary configuration file
|
9
|
+
# @see Muzak::Config
|
5
10
|
CONFIG_FILE = File.join(CONFIG_DIR, "muzak.yml").freeze
|
11
|
+
|
12
|
+
# Muzak's music index
|
6
13
|
INDEX_FILE = File.join(CONFIG_DIR, "index.dat").freeze
|
14
|
+
|
15
|
+
# The directory for all user playlists
|
7
16
|
PLAYLIST_DIR = File.join(CONFIG_DIR, "playlists").freeze
|
17
|
+
|
18
|
+
# The directory for all user plugins
|
8
19
|
USER_PLUGIN_DIR = File.join(CONFIG_DIR, "plugins").freeze
|
20
|
+
|
21
|
+
# The directory for all user commands
|
9
22
|
USER_COMMAND_DIR = File.join(CONFIG_DIR, "commands").freeze
|
10
23
|
|
24
|
+
# All events currently propagated by {Muzak::Instance#event}
|
11
25
|
PLUGIN_EVENTS = [
|
12
26
|
:player_activated,
|
13
27
|
:player_deactivated,
|
14
28
|
:song_loaded,
|
29
|
+
:song_unloaded,
|
15
30
|
:playlist_enqueued
|
16
31
|
]
|
17
32
|
end
|
data/lib/muzak/index.rb
CHANGED
@@ -1,8 +1,22 @@
|
|
1
1
|
module Muzak
|
2
|
+
# Represents muzak's music index.
|
2
3
|
class Index
|
3
4
|
include Utils
|
4
|
-
attr_accessor :tree, :deep, :hash
|
5
5
|
|
6
|
+
# @return [String] the path of the root of the music tree
|
7
|
+
attr_accessor :tree
|
8
|
+
|
9
|
+
# @return [Boolean] whether the index is "deep" (includes metadata) or not
|
10
|
+
attr_accessor :deep
|
11
|
+
|
12
|
+
# @return [Hash] the index hash
|
13
|
+
attr_accessor :hash
|
14
|
+
|
15
|
+
# @param tree [String] the root to begin indexing from
|
16
|
+
# @param deep [Boolean] whether to build a "deep" index
|
17
|
+
# @note if the index ({Muzak::INDEX_FILE}) already exists and is not
|
18
|
+
# outdated, no building is performed.
|
19
|
+
# @see #build!
|
6
20
|
def initialize(tree, deep: false)
|
7
21
|
@tree = tree
|
8
22
|
@deep = deep
|
@@ -16,6 +30,8 @@ module Muzak
|
|
16
30
|
build!
|
17
31
|
end
|
18
32
|
|
33
|
+
# (Re)builds and saves the index ({Muzak::INDEX_FILE}) to disk.
|
34
|
+
# @note This method can be expensive.
|
19
35
|
def build!
|
20
36
|
@hash = build_index_hash!
|
21
37
|
|
@@ -24,22 +40,30 @@ module Muzak
|
|
24
40
|
File.open(INDEX_FILE, "w") { |io| io.write Marshal::dump @hash }
|
25
41
|
end
|
26
42
|
|
43
|
+
# @return [Boolean] whether or not the current index is deep
|
27
44
|
def deep?
|
28
45
|
deep
|
29
46
|
end
|
30
47
|
|
48
|
+
# @return [Integer] the UNIX timestamp from when the index was built
|
31
49
|
def timestamp
|
32
50
|
@hash["timestamp"]
|
33
51
|
end
|
34
52
|
|
53
|
+
# @return [Boolean] whether or not the index is currently out of date
|
54
|
+
# @note The behavior of this method is affected by the value of
|
55
|
+
# {Muzak::Config.index_autobuild}.
|
35
56
|
def outdated?
|
36
57
|
Time.now.to_i - timestamp >= Config.index_autobuild
|
37
58
|
end
|
38
59
|
|
60
|
+
# @return [Array<String>] a list of all artists in the index
|
39
61
|
def artists
|
40
62
|
@artists ||= @hash["artists"].keys
|
41
63
|
end
|
42
64
|
|
65
|
+
# @return [Hash{String => Album}] a hash of all album names with their
|
66
|
+
# {Album} objects
|
43
67
|
def albums
|
44
68
|
@albums_hash ||= begin
|
45
69
|
albums_hash = {}
|
@@ -54,10 +78,15 @@ module Muzak
|
|
54
78
|
end
|
55
79
|
end
|
56
80
|
|
81
|
+
# @return [Array<String>] a list of all albums in the index
|
82
|
+
# @note albums with the same name will appear, but can't be disambiguated
|
83
|
+
# from here
|
57
84
|
def album_names
|
58
85
|
artists.map { |a| @hash["artists"][a]["albums"].keys }.flatten
|
59
86
|
end
|
60
87
|
|
88
|
+
# @param artist [String] the artist's name
|
89
|
+
# @return [Array<Album>] all albums by the given artist
|
61
90
|
def albums_by(artist)
|
62
91
|
if artists.include?(artist)
|
63
92
|
@hash["artists"][artist]["albums"].map { |title, album| Album.new(title, album) }
|
@@ -67,6 +96,9 @@ module Muzak
|
|
67
96
|
end
|
68
97
|
end
|
69
98
|
|
99
|
+
# Produces a 'jukebox' of random songs.
|
100
|
+
# @param count [Integer] the number of random songs to return
|
101
|
+
# @return [Array<Song>] an array of randomly chosen songs
|
70
102
|
def jukebox(count = 50)
|
71
103
|
@all_albums ||= @hash["artists"].map { |_, a| a["albums"] }.flatten
|
72
104
|
|
@@ -79,6 +111,10 @@ module Muzak
|
|
79
111
|
end
|
80
112
|
end
|
81
113
|
|
114
|
+
# @param artist [String] the artist's name
|
115
|
+
# @return [Array<Song>] an array of all the artist's songs
|
116
|
+
# @note no inter-album order is guaranteed. songs within an album are
|
117
|
+
# generally sorted by track number.
|
82
118
|
def songs_by(artist)
|
83
119
|
error "no such artist: '#{artist}'" unless @hash["artists"].key?(artist)
|
84
120
|
|