muzak 0.4.0 → 0.4.1
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/CONFIGURATION.md +38 -0
- data/lib/muzak.rb +1 -1
- data/lib/muzak/config.rb +1 -0
- data/lib/muzak/index.rb +2 -1
- data/lib/muzak/instance.rb +2 -0
- data/lib/muzak/player/mpd.rb +153 -0
- data/lib/muzak/player/mpv.rb +1 -2
- data/lib/muzak/player/multiplayer.rb +141 -0
- data/lib/muzak/player/vlc.rb +1 -1
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d627d0c95c41896f1c8acb0b47403f240924571
|
4
|
+
data.tar.gz: 11f8e33ea6d45befe35fdffcc20b1cba87a05b7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6581bb5f6a785076619b44596f09ab3835a47be33e23e0e0bd1b1b032caee4ceefde24144abbc23c0e09d4158abc86ee7e33fbb04a09e1c3d91b336aded6ded
|
7
|
+
data.tar.gz: 6c46c4694d1cfbb67e2e9cbfdbd2eb02899747cef65d10a195efd8daccb27dcc0b39a737108923e11d8470b73bb7f4b59761755936a6095d095b93a263151ec2
|
data/CONFIGURATION.md
CHANGED
@@ -76,6 +76,16 @@ These are the configuration keys observed by muzak's "core," particularly
|
|
76
76
|
|
77
77
|
In no particular order:
|
78
78
|
|
79
|
+
### `event`
|
80
|
+
|
81
|
+
*Optional.*
|
82
|
+
|
83
|
+
*Default:* `true`
|
84
|
+
|
85
|
+
If `event: false` is set in the configuration file, then muzak will not
|
86
|
+
attempt to propagate events to plugins. This might be useful for debugging
|
87
|
+
or when using multiple players at once via {Muzak::Player::MultiPlayer}.
|
88
|
+
|
79
89
|
### `debug`
|
80
90
|
|
81
91
|
*Optional.*
|
@@ -131,6 +141,34 @@ set, then `mpv` will be instructed to disable all video output entirely.
|
|
131
141
|
This option is primarily useful in conjunction with plugins that provide
|
132
142
|
album art display, or for making Muzak entirely non-graphical.
|
133
143
|
|
144
|
+
### `multiplayer-players`
|
145
|
+
|
146
|
+
*Mandatory if using `multiplayer`.*
|
147
|
+
|
148
|
+
*No default.*
|
149
|
+
|
150
|
+
If the `player` key is set to `multiplayer`, then this should be set to the
|
151
|
+
array of players to use together. For example,
|
152
|
+
`multiplayer-players: [mpv, mpd]`.
|
153
|
+
|
154
|
+
### `mpd-host`
|
155
|
+
|
156
|
+
*Optional.*
|
157
|
+
|
158
|
+
*Default:* `localhost`
|
159
|
+
|
160
|
+
If `mpd-host` is set *and* the `mpd` player is used, then `mpd` will use this
|
161
|
+
value as the MPD host to connect to.
|
162
|
+
|
163
|
+
### `mpd-port`
|
164
|
+
|
165
|
+
*Optional.*
|
166
|
+
|
167
|
+
*Default:* `6600`
|
168
|
+
|
169
|
+
If `mpd-port` is set *and* the `mpd` player is used, then `mpd` will use this
|
170
|
+
value as the MPD port to connect to.
|
171
|
+
|
134
172
|
### `jukebox-size`
|
135
173
|
|
136
174
|
*Mandatory.*
|
data/lib/muzak.rb
CHANGED
data/lib/muzak/config.rb
CHANGED
data/lib/muzak/index.rb
CHANGED
@@ -38,6 +38,7 @@ module Muzak
|
|
38
38
|
def reload!
|
39
39
|
debug "reloading index from '#{file}'..."
|
40
40
|
@hash = Marshal.load(File.read file)
|
41
|
+
@albums_hash = nil
|
41
42
|
memoize_collections!
|
42
43
|
end
|
43
44
|
|
@@ -53,7 +54,7 @@ module Muzak
|
|
53
54
|
|
54
55
|
# @return [Array<String>] a list of all artists in the index
|
55
56
|
def artists
|
56
|
-
@
|
57
|
+
@hash["artists"].keys
|
57
58
|
end
|
58
59
|
|
59
60
|
# @return [Hash{String => Album}] a hash of all album names with their
|
data/lib/muzak/instance.rb
CHANGED
@@ -61,6 +61,8 @@ module Muzak
|
|
61
61
|
# @return [void]
|
62
62
|
# @note {Config::PLUGIN_EVENTS} contains all valid events.
|
63
63
|
def event(type, *args)
|
64
|
+
# don't propagate events if disabled by the user
|
65
|
+
return unless Config.events
|
64
66
|
return unless Config::PLUGIN_EVENTS.include?(type)
|
65
67
|
|
66
68
|
plugins.each do |plugin|
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require "ruby-mpd"
|
2
|
+
|
3
|
+
module Muzak
|
4
|
+
module Player
|
5
|
+
# Exposes a MPD connection to muzak for playback control.
|
6
|
+
class MPD < StubPlayer
|
7
|
+
def running?
|
8
|
+
!!@mpd&.connected?
|
9
|
+
end
|
10
|
+
|
11
|
+
# Activates the MPD connection.
|
12
|
+
# @return [void]
|
13
|
+
def activate!
|
14
|
+
return if running?
|
15
|
+
|
16
|
+
debug "activating #{self.class}"
|
17
|
+
|
18
|
+
host = Config.mpd_host || "localhost"
|
19
|
+
port = Config.mpd_port || 6600
|
20
|
+
|
21
|
+
@mpd = ::MPD.new host, port
|
22
|
+
@mpd.connect
|
23
|
+
@mpd.clear
|
24
|
+
|
25
|
+
instance.event :player_activated
|
26
|
+
end
|
27
|
+
|
28
|
+
# Deactivates the MPD connection.
|
29
|
+
# @return [void]
|
30
|
+
def deactivate!
|
31
|
+
@mpd.clear
|
32
|
+
sleep 0.1 # give mpd a little bit of time to process
|
33
|
+
@mpd.disconnect
|
34
|
+
|
35
|
+
debug "deactivating #{self.class}"
|
36
|
+
|
37
|
+
instance.event :player_deactivated
|
38
|
+
end
|
39
|
+
|
40
|
+
# Tell MPD to begin playback.
|
41
|
+
# @return [void]
|
42
|
+
# @note Does nothing is playback is already in progress.
|
43
|
+
def play
|
44
|
+
@mpd.play
|
45
|
+
end
|
46
|
+
|
47
|
+
# Tell MPD to pause playback.
|
48
|
+
# @return [void]
|
49
|
+
# @note Does nothing is playback is already paused.
|
50
|
+
def pause
|
51
|
+
@mpd.pause
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Boolean] whether or not MPD is currently playing.
|
55
|
+
def playing?
|
56
|
+
return false unless running?
|
57
|
+
|
58
|
+
@mpd.playing?
|
59
|
+
end
|
60
|
+
|
61
|
+
# Tell MPD to play the next song in its queue.
|
62
|
+
# @return [void]
|
63
|
+
# @note Does nothing if the current song is the last.
|
64
|
+
def next_song
|
65
|
+
@mpd.next
|
66
|
+
end
|
67
|
+
|
68
|
+
# Tell MPD to play the previous song in its queue.
|
69
|
+
# @return [void]
|
70
|
+
# @note Restarts the song if the current song is the first.
|
71
|
+
def previous_song
|
72
|
+
@mpd.previous
|
73
|
+
end
|
74
|
+
|
75
|
+
# Tell MPD to add the given song to its queue.
|
76
|
+
# @param song [Song] the song to add
|
77
|
+
# @return [void]
|
78
|
+
# @note Activates MPD if not already activated.
|
79
|
+
def enqueue_song(song)
|
80
|
+
activate! unless running?
|
81
|
+
|
82
|
+
load_song song
|
83
|
+
end
|
84
|
+
|
85
|
+
# Tell MPD to add the given album to its queue.
|
86
|
+
# @param album [Album] the album to add
|
87
|
+
# @return [void]
|
88
|
+
# @note Activates MPD if not already activated.
|
89
|
+
def enqueue_album(album)
|
90
|
+
activate! unless running?
|
91
|
+
|
92
|
+
album.songs.each do |song|
|
93
|
+
load_song song
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Tell MPD to add the given playlist to its queue.
|
98
|
+
# @param playlist [Playlist] the playlist to add
|
99
|
+
# @return [void]
|
100
|
+
# @note Activates MPD if not already activated.
|
101
|
+
def enqueue_playlist(playlist)
|
102
|
+
activate! unless running?
|
103
|
+
|
104
|
+
playlist.songs.each do |song|
|
105
|
+
load_song song
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Get MPD's internal queue.
|
110
|
+
# @return [Array<Song>] all songs in MPD's queue
|
111
|
+
# @note This includes songs already played.
|
112
|
+
# @todo Implement this.
|
113
|
+
def list_queue
|
114
|
+
debug @mpd.playlist.to_s
|
115
|
+
danger "this player doesn't support list_queue"
|
116
|
+
[]
|
117
|
+
end
|
118
|
+
|
119
|
+
# Shuffle MPD's internal queue.
|
120
|
+
# @return [void]
|
121
|
+
# @todo Implement this.
|
122
|
+
def shuffle
|
123
|
+
danger "this player doesn't support shuffling (?)"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Clear MPD's internal queue.
|
127
|
+
# @return [void]
|
128
|
+
def clear_queue
|
129
|
+
return unless running?
|
130
|
+
@mpd.clear
|
131
|
+
end
|
132
|
+
|
133
|
+
# Get MPD's currently loaded song.
|
134
|
+
# @return [Song, nil] the currently loaded song
|
135
|
+
def now_playing
|
136
|
+
return unless playing?
|
137
|
+
|
138
|
+
path = "#{Config.music}/#{@mpd.current_song.file}"
|
139
|
+
Song.new(path)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Load a song into MPD.
|
143
|
+
# @param song [Song] the song to load
|
144
|
+
# @return [void]
|
145
|
+
# @api private
|
146
|
+
def load_song(song)
|
147
|
+
path = song.path.sub("#{Config.music}/", "")
|
148
|
+
@mpd.add(path)
|
149
|
+
@mpd.play if Config.autoplay
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
data/lib/muzak/player/mpv.rb
CHANGED
@@ -0,0 +1,141 @@
|
|
1
|
+
module Muzak
|
2
|
+
module Player
|
3
|
+
# Wraps multiple players into a single class.
|
4
|
+
# This can be useful for controlling a local and remote player
|
5
|
+
# simultaneously, e.g. one {MPD} and one {MPV} via the same Muzak instance.
|
6
|
+
class MultiPlayer < StubPlayer
|
7
|
+
# @return [Array<StubPlayer>] the players associated with this multiplayer
|
8
|
+
attr_reader :players
|
9
|
+
|
10
|
+
# @return [Boolean] whether or not all of the players are available
|
11
|
+
def self.available?
|
12
|
+
klasses = Config.multiplayer_players.map { |p| Player::PLAYER_MAP[p] }
|
13
|
+
klasses.all?(&:available?)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param instance [Instance] the instance associated with the player
|
17
|
+
def initialize(instance)
|
18
|
+
super(instance)
|
19
|
+
|
20
|
+
klasses = Config.multiplayer_players.map { |p| Player::PLAYER_MAP[p] }
|
21
|
+
@players = klasses.map { |pk| pk.new(instance) }
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Boolean] whether or not any of the players are currently running.
|
25
|
+
def running?
|
26
|
+
@players.any?(&:running?)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Activates each player under the multiplayer.
|
30
|
+
# @return [void]
|
31
|
+
def activate!
|
32
|
+
debug "activating #{self.class}"
|
33
|
+
@players.each(&:activate!)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Deactivates each player under the multiplayer.
|
37
|
+
# @return [void]
|
38
|
+
def deactivate!
|
39
|
+
debug "deactivating #{self.class}"
|
40
|
+
@players.each(&:deactivate!)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Tell all players to begin playback.
|
44
|
+
# @return [void]
|
45
|
+
# @note Does nothing is playback is already in progress.
|
46
|
+
def play
|
47
|
+
return unless running?
|
48
|
+
@players.each(&:play)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Tell all players to pause playback.
|
52
|
+
# @return [void]
|
53
|
+
# @note Does nothing is playback is already paused.
|
54
|
+
def pause
|
55
|
+
return unless running?
|
56
|
+
@players.each(&:pause)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Boolean] Whether or not any of the players are currently playing.
|
60
|
+
def playing?
|
61
|
+
return false unless running?
|
62
|
+
@players.any?(&:playing?)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Tell all players to play the next song in its queue.
|
66
|
+
# @return [void]
|
67
|
+
# @note Does nothing if the current song is the last.
|
68
|
+
def next_song
|
69
|
+
@players.each(&:next_song)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Tell all players to play the previous song in its queue.
|
73
|
+
# @return [void]
|
74
|
+
# @note Does nothing if the current song is the first.
|
75
|
+
def previous_song
|
76
|
+
@players.each(&:previous_song)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Tell all players to add the given song to its queue.
|
80
|
+
# @param song [Song] the song to add
|
81
|
+
# @return [void]
|
82
|
+
# @note Activates all players if not already activated.
|
83
|
+
def enqueue_song(song)
|
84
|
+
activate! unless running?
|
85
|
+
@players.each { |p| p.enqueue_song(song) }
|
86
|
+
end
|
87
|
+
|
88
|
+
# Tell all players to add the given album to its queue.
|
89
|
+
# @param album [Album] the album to add
|
90
|
+
# @return [void]
|
91
|
+
# @note Activates all players if not already activated.
|
92
|
+
def enqueue_album(album)
|
93
|
+
activate! unless running?
|
94
|
+
@players.each { |p| p.enqueue_album(album) }
|
95
|
+
end
|
96
|
+
|
97
|
+
# Tell all players to add the given playlist to its queue.
|
98
|
+
# @param playlist [Playlist] the playlist to add
|
99
|
+
# @return [void]
|
100
|
+
# @note Activates all players if not already activated.
|
101
|
+
def enqueue_playlist(playlist)
|
102
|
+
activate! unless running?
|
103
|
+
@players.each { |p| p.enqueue_playlist(playlist) }
|
104
|
+
end
|
105
|
+
|
106
|
+
# Get the internal queue of the first player.
|
107
|
+
# @return [Array<Song>] all songs in all players's queue
|
108
|
+
# @note This includes songs already played.
|
109
|
+
def list_queue
|
110
|
+
@players.first.list_queue
|
111
|
+
end
|
112
|
+
|
113
|
+
# Shuffle the internal queue.
|
114
|
+
# @return [void]
|
115
|
+
def shuffle_queue
|
116
|
+
return unless running?
|
117
|
+
# XXX: shuffling is currently done internally within each player,
|
118
|
+
# meaning that shuffling within multiplayer would leave each
|
119
|
+
# player in an inconsistent queue state.
|
120
|
+
# the solution to this is probably to list the queue, shuffle that
|
121
|
+
# list, clear the player's queue, and then load the single shuffled
|
122
|
+
# list back into each player.
|
123
|
+
danger "shuffling doesn't currently make any sense in multiplayer!"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Clears the internal queue.
|
127
|
+
# @return [void]
|
128
|
+
def clear_queue
|
129
|
+
return unless running?
|
130
|
+
@players.each(&:clear_queue)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Get the currently loaded song.
|
134
|
+
# @return [Song, nil] the currently loaded song
|
135
|
+
def now_playing
|
136
|
+
@players[1].now_playing
|
137
|
+
@players.first.now_playing
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/lib/muzak/player/vlc.rb
CHANGED
@@ -46,7 +46,6 @@ module Muzak
|
|
46
46
|
@vlc.play
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
49
|
# Tell VLC to pause playback.
|
51
50
|
# @return [void]
|
52
51
|
# @note Does nothing is playback is already paused.
|
@@ -130,6 +129,7 @@ module Muzak
|
|
130
129
|
# Clear VLC's internal queue.
|
131
130
|
# @return [void]
|
132
131
|
def clear_queue
|
132
|
+
return unless running?
|
133
133
|
@vlc.clear
|
134
134
|
end
|
135
135
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: muzak
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Woodruff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: taglib-ruby
|
@@ -72,6 +72,20 @@ dependencies:
|
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: 0.10.0
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: ruby-mpd
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.3.3
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.3.3
|
75
89
|
description: A library for controlling playlists and media players.
|
76
90
|
email: william@tuffbizz.com
|
77
91
|
executables:
|
@@ -105,7 +119,9 @@ files:
|
|
105
119
|
- lib/muzak/index.rb
|
106
120
|
- lib/muzak/instance.rb
|
107
121
|
- lib/muzak/player.rb
|
122
|
+
- lib/muzak/player/mpd.rb
|
108
123
|
- lib/muzak/player/mpv.rb
|
124
|
+
- lib/muzak/player/multiplayer.rb
|
109
125
|
- lib/muzak/player/stub_player.rb
|
110
126
|
- lib/muzak/player/vlc.rb
|
111
127
|
- lib/muzak/playlist.rb
|
@@ -133,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
149
|
version: '0'
|
134
150
|
requirements: []
|
135
151
|
rubyforge_project:
|
136
|
-
rubygems_version: 2.6.
|
152
|
+
rubygems_version: 2.6.11
|
137
153
|
signing_key:
|
138
154
|
specification_version: 4
|
139
155
|
summary: muzak - A metamusic player.
|