muzak 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|