anyplayer 1.1.1 → 1.2.0
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 +7 -0
- data/.gitignore +1 -1
- data/.ruby-version +1 -0
- data/.travis.yml +1 -2
- data/CHANGELOG.md +76 -0
- data/CONTRIBUTING.md +22 -0
- data/Gemfile +0 -2
- data/MIT-LICENSE +20 -0
- data/README.md +20 -14
- data/Rakefile +10 -0
- data/anyplayer.gemspec +3 -0
- data/bin/rake +29 -0
- data/lib/anyplayer.rb +8 -2
- data/lib/anyplayer/command_line.rb +56 -26
- data/lib/anyplayer/player.rb +15 -7
- data/lib/anyplayer/players/amarok.rb +25 -19
- data/lib/anyplayer/players/itunes_mac.rb +22 -17
- data/lib/anyplayer/players/itunes_windows.rb +9 -6
- data/lib/anyplayer/players/mpd.rb +14 -8
- data/lib/anyplayer/players/noplayer.rb +2 -2
- data/lib/anyplayer/players/rdio_mac.rb +22 -18
- data/lib/anyplayer/players/rhythmbox.rb +15 -15
- data/lib/anyplayer/players/spotify_mac.rb +21 -17
- data/lib/anyplayer/players/xmms2.rb +34 -24
- data/lib/anyplayer/selector.rb +63 -32
- data/lib/anyplayer/version.rb +1 -1
- data/test/anyplayer_test.rb +12 -6
- data/test/command_line_test.rb +150 -0
- data/test/player_test.rb +44 -7
- data/test/players/mpd_test.rb +2 -4
- data/test/selector_test.rb +2 -2
- data/test/test_helper.rb +1 -2
- metadata +39 -26
- data/Gemfile.lock +0 -22
@@ -1,77 +1,87 @@
|
|
1
1
|
class Anyplayer::Xmms2 < Anyplayer::Player
|
2
2
|
def playpause
|
3
|
-
xmms2
|
3
|
+
xmms2 "toggle"
|
4
4
|
end
|
5
5
|
|
6
6
|
def play
|
7
|
-
xmms2
|
7
|
+
xmms2 "play"
|
8
8
|
end
|
9
9
|
|
10
10
|
def pause
|
11
|
-
xmms2
|
11
|
+
xmms2 "pause"
|
12
12
|
end
|
13
13
|
|
14
14
|
def prev
|
15
|
-
xmms2
|
15
|
+
xmms2 "prev"
|
16
16
|
super
|
17
17
|
end
|
18
18
|
|
19
19
|
def next
|
20
|
-
xmms2
|
20
|
+
xmms2 "next"
|
21
21
|
super
|
22
22
|
end
|
23
23
|
|
24
24
|
def voldown
|
25
|
-
|
26
|
-
new_volume = (current < 11 ? 0 : current - 10)
|
27
|
-
xmms2 "server volume #{new_volume}"
|
25
|
+
set_volume volume - 10
|
28
26
|
end
|
29
27
|
|
30
28
|
def volup
|
31
|
-
|
32
|
-
new_volume = (current > 89 ? 100 : current + 10)
|
33
|
-
xmms2 "server volume #{new_volume}"
|
29
|
+
set_volume volume + 10
|
34
30
|
end
|
35
31
|
|
36
32
|
def volume
|
37
33
|
# currently just the first (left?) channel
|
38
|
-
xmms2(
|
39
|
-
$1
|
34
|
+
xmms2("server volume").split("\n").first.sub(/([^0-9]*)/, "").to_i
|
40
35
|
end
|
41
36
|
|
42
37
|
def track
|
43
|
-
xmms2 "
|
38
|
+
xmms2 "current -f '${title}'"
|
44
39
|
end
|
45
40
|
|
46
41
|
def artist
|
47
|
-
xmms2 "
|
42
|
+
xmms2 "current -f '${artist}'"
|
48
43
|
end
|
49
44
|
|
50
45
|
def album
|
51
|
-
xmms2 "
|
46
|
+
xmms2 "current -f '${album}'"
|
52
47
|
end
|
53
48
|
|
54
49
|
def playing?
|
55
|
-
xmms2("
|
50
|
+
xmms2("current -f '${playback_status}'") == "Playing"
|
56
51
|
end
|
57
52
|
|
58
53
|
def paused?
|
59
|
-
xmms2("
|
54
|
+
xmms2("current -f '${playback_status}'") == "Paused"
|
60
55
|
end
|
61
56
|
|
62
57
|
def launched?
|
63
58
|
# xmms2 autolaunches the daemon, so this should always be true
|
64
|
-
%x(xmms2
|
59
|
+
%x(xmms2 current 2> /dev/null)
|
65
60
|
$? == 0
|
66
61
|
end
|
67
62
|
|
68
63
|
def host
|
69
|
-
ENV[
|
64
|
+
ENV["XMMS_PATH"] || super
|
65
|
+
end
|
66
|
+
|
67
|
+
def platforms
|
68
|
+
[:unix, :linux]
|
70
69
|
end
|
71
70
|
|
72
71
|
private
|
73
|
-
def xmms2(command)
|
74
|
-
%x(xmms2 #{command}).split("\n").first.strip
|
75
|
-
end
|
76
|
-
end
|
77
72
|
|
73
|
+
def xmms2(command)
|
74
|
+
ret = %x(xmms2 #{command}).split("\n").first
|
75
|
+
ret ? ret.strip : ""
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_volume(num)
|
79
|
+
num = if num < 0
|
80
|
+
0
|
81
|
+
elsif num > 100
|
82
|
+
100
|
83
|
+
end
|
84
|
+
|
85
|
+
xmms2 "server volume #{num}"
|
86
|
+
end
|
87
|
+
end
|
data/lib/anyplayer/selector.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
require "rbconfig"
|
2
|
+
|
3
|
+
# The Selector is the tool that will find you the currently running player
|
4
|
+
# on your platform.
|
2
5
|
#
|
3
6
|
# Example:
|
4
7
|
#
|
@@ -7,62 +10,90 @@
|
|
7
10
|
# player = selector.player
|
8
11
|
#
|
9
12
|
# Needs the PLAYERS constant to contain a list of players.
|
13
|
+
module Anyplayer
|
14
|
+
class Selector
|
15
|
+
attr_accessor :verbose
|
16
|
+
attr_reader :errors
|
10
17
|
|
11
|
-
|
12
|
-
|
13
|
-
|
18
|
+
def initialize
|
19
|
+
@verbose = false
|
20
|
+
@errors = []
|
21
|
+
end
|
14
22
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
23
|
+
# Returns an instance of the first music player that's launched
|
24
|
+
def player
|
25
|
+
PLAYERS.each do |player|
|
26
|
+
player_load(player) || next
|
19
27
|
|
20
|
-
|
21
|
-
|
22
|
-
players_for_this_platform.each { |player|
|
23
|
-
player_load(player) or next
|
24
|
-
instance = player_class(player).new
|
25
|
-
return instance if player_launched(instance)
|
26
|
-
}
|
27
|
-
nil
|
28
|
-
end
|
28
|
+
instance = player_class(player).new
|
29
|
+
player_on_platform?(instance) || next
|
29
30
|
|
31
|
+
return instance if player_launched?(instance)
|
32
|
+
end
|
33
|
+
nil
|
34
|
+
end
|
30
35
|
|
31
|
-
|
36
|
+
private
|
32
37
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
def platform
|
39
|
+
@platform ||= begin
|
40
|
+
host_os = RbConfig::CONFIG["host_os"]
|
41
|
+
case host_os
|
42
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
43
|
+
:windows
|
44
|
+
when /darwin|mac os/
|
45
|
+
:mac
|
46
|
+
when /linux/
|
47
|
+
:linux
|
48
|
+
when /solaris|bsd/
|
49
|
+
:unix
|
50
|
+
else
|
51
|
+
@errors << "Unknown operating system #{host_os.inspect}"
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
end
|
38
55
|
end
|
39
56
|
|
40
57
|
def player_load(player)
|
58
|
+
log "#{player}:"
|
41
59
|
begin
|
42
60
|
require "anyplayer/players/#{player}"
|
43
|
-
|
61
|
+
log " loaded"
|
44
62
|
true
|
45
63
|
rescue LoadError => e
|
46
|
-
|
64
|
+
log " #{e.message}"
|
47
65
|
@errors << "Error loading #{player}: #{e.message}"
|
48
66
|
false
|
49
67
|
end
|
50
68
|
end
|
51
69
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
70
|
+
def player_on_platform?(player)
|
71
|
+
result = player.platforms.include?(platform)
|
72
|
+
log " not on platform" unless result
|
73
|
+
result
|
55
74
|
end
|
56
75
|
|
57
|
-
def
|
58
|
-
|
76
|
+
def player_class(player)
|
77
|
+
camelized = player.to_s.split(/_/).map(&:capitalize).join
|
78
|
+
Anyplayer.const_get(camelized)
|
79
|
+
end
|
59
80
|
|
81
|
+
def player_launched?(player)
|
60
82
|
seconds = 5
|
61
83
|
begin
|
62
|
-
Timeout
|
84
|
+
Timeout.timeout(seconds) do
|
85
|
+
launched = player.launched?
|
86
|
+
log launched ? " launched" : " not launched"
|
87
|
+
launched
|
88
|
+
end
|
63
89
|
rescue Timeout::Error
|
64
|
-
|
90
|
+
log " timed out after #{seconds} seconds"
|
65
91
|
false
|
66
92
|
end
|
67
93
|
end
|
94
|
+
|
95
|
+
def log(text)
|
96
|
+
$stderr.puts text if verbose
|
97
|
+
end
|
98
|
+
end
|
68
99
|
end
|
data/lib/anyplayer/version.rb
CHANGED
data/test/anyplayer_test.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
class AnyplayerTest <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
class AnyplayerTest < Minitest::Test
|
4
|
+
def test_loading_all_players_does_not_explode
|
5
|
+
PLAYERS.each do |player|
|
6
|
+
require "anyplayer/players/#{player}"
|
7
|
+
end
|
8
|
+
rescue LoadError
|
9
|
+
# Allow LoadErrors that depend on Windows
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_launched
|
13
|
+
assert_kind_of Anyplayer::Player, Anyplayer.launched
|
14
|
+
end
|
9
15
|
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "anyplayer/command_line"
|
3
|
+
|
4
|
+
class CommandLineTest < Minitest::Test
|
5
|
+
USAGE = "Usage: anyplayer [-v] [command]
|
6
|
+
|
7
|
+
Where command is one of: playpause, play, pause, next, prev, voldown, volup, volume, track, artist, album, vote, name, launched, paused, playing.
|
8
|
+
|
9
|
+
Player connected: Fake Player.
|
10
|
+
"
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@player = flexmock(:player)
|
14
|
+
@selector = flexmock(:selector)
|
15
|
+
@selector.should_receive(:player).and_return(@player)
|
16
|
+
flexmock(Anyplayer::Selector).should_receive(:new).and_return(@selector)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_no_command
|
20
|
+
flexmock(@player).should_receive(:name).once.and_return("Fake Player")
|
21
|
+
flexmock($stderr).should_receive(:puts).once.with(USAGE)
|
22
|
+
flexmock(Anyplayer::CommandLine).should_receive(:exit).once.with(1)
|
23
|
+
Anyplayer::CommandLine.parse(%w())
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_wrong_command
|
27
|
+
flexmock(@player).should_receive(:name).once.and_return("Fake Player")
|
28
|
+
flexmock($stderr).should_receive(:puts).once.with(USAGE)
|
29
|
+
flexmock(Anyplayer::CommandLine).should_receive(:exit).once.with(1)
|
30
|
+
Anyplayer::CommandLine.parse(%w(err))
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_verbose
|
34
|
+
# flexmock(@player).should_receive(:name).once.and_return("Foo")
|
35
|
+
flexmock(@player).should_receive(:play).once
|
36
|
+
flexmock(@selector).should_receive(:verbose=).once.with(true)
|
37
|
+
flexmock($stderr).should_receive(:puts).once.with(/^anyplayer v[0-9.]+$/)
|
38
|
+
Anyplayer::CommandLine.parse(%w(-v play))
|
39
|
+
end
|
40
|
+
|
41
|
+
# Actions
|
42
|
+
|
43
|
+
def test_playpause
|
44
|
+
flexmock(@player).should_receive(:playpause).once
|
45
|
+
Anyplayer::CommandLine.parse(%w(playpause))
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_play
|
49
|
+
flexmock(@player).should_receive(:play).once
|
50
|
+
Anyplayer::CommandLine.parse(%w(play))
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_pause
|
54
|
+
flexmock(@player).should_receive(:pause).once
|
55
|
+
Anyplayer::CommandLine.parse(%w(pause))
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_next
|
59
|
+
flexmock(@player).should_receive(:next).once
|
60
|
+
Anyplayer::CommandLine.parse(%w(next))
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_prev
|
64
|
+
flexmock(@player).should_receive(:prev).once
|
65
|
+
Anyplayer::CommandLine.parse(%w(prev))
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_voldown
|
69
|
+
flexmock(@player).should_receive(:voldown).once
|
70
|
+
Anyplayer::CommandLine.parse(%w(voldown))
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_volup
|
74
|
+
flexmock(@player).should_receive(:volup).once
|
75
|
+
Anyplayer::CommandLine.parse(%w(volup))
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_vote
|
79
|
+
flexmock(@player).should_receive(:vote).once
|
80
|
+
Anyplayer::CommandLine.parse(%w(vote))
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_volume
|
84
|
+
flexmock(@player).should_receive(:volume).once.and_return(42)
|
85
|
+
flexmock($stdout).should_receive(:puts).once.with(42)
|
86
|
+
Anyplayer::CommandLine.parse(%w(volume))
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_track
|
90
|
+
flexmock(@player).should_receive(:track).once.and_return("Foo")
|
91
|
+
flexmock($stdout).should_receive(:puts).once.with("Foo")
|
92
|
+
Anyplayer::CommandLine.parse(%w(track))
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_artist
|
96
|
+
flexmock(@player).should_receive(:artist).once.and_return("Foo")
|
97
|
+
flexmock($stdout).should_receive(:puts).once.with("Foo")
|
98
|
+
Anyplayer::CommandLine.parse(%w(artist))
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_album
|
102
|
+
flexmock(@player).should_receive(:album).once.and_return("Foo")
|
103
|
+
flexmock($stdout).should_receive(:puts).once.with("Foo")
|
104
|
+
Anyplayer::CommandLine.parse(%w(album))
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_name
|
108
|
+
flexmock(@player).should_receive(:name).once.and_return("Foo")
|
109
|
+
flexmock($stdout).should_receive(:puts).once.with("Foo")
|
110
|
+
Anyplayer::CommandLine.parse(%w(name))
|
111
|
+
end
|
112
|
+
|
113
|
+
# Booleans
|
114
|
+
|
115
|
+
def test_launched_true
|
116
|
+
flexmock(Anyplayer::CommandLine).should_receive(:exit) # .with(1)
|
117
|
+
flexmock(@player).should_receive(:launched?).once.and_return(true)
|
118
|
+
Anyplayer::CommandLine.parse(%w(launched))
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_launched_false
|
122
|
+
flexmock(Anyplayer::CommandLine).should_receive(:exit) # .with(0)
|
123
|
+
flexmock(@player).should_receive(:launched?).once.and_return(false)
|
124
|
+
Anyplayer::CommandLine.parse(%w(launched))
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_playing_true
|
128
|
+
flexmock(Anyplayer::CommandLine).should_receive(:exit).once # .with(1)
|
129
|
+
flexmock(@player).should_receive(:playing?).once.and_return(true)
|
130
|
+
Anyplayer::CommandLine.parse(%w(playing))
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_playing_false
|
134
|
+
flexmock(Anyplayer::CommandLine).should_receive(:exit).once # .with(0)
|
135
|
+
flexmock(@player).should_receive(:playing?).once.and_return(false)
|
136
|
+
Anyplayer::CommandLine.parse(%w(playing))
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_paused_true
|
140
|
+
flexmock(Anyplayer::CommandLine).should_receive(:exit).once # .with(1)
|
141
|
+
flexmock(@player).should_receive(:paused?).once.and_return(true)
|
142
|
+
Anyplayer::CommandLine.parse(%w(paused))
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_paused_false
|
146
|
+
flexmock(Anyplayer::CommandLine).should_receive(:exit).once # .with(0)
|
147
|
+
flexmock(@player).should_receive(:paused?).once.and_return(false)
|
148
|
+
Anyplayer::CommandLine.parse(%w(paused))
|
149
|
+
end
|
150
|
+
end
|
data/test/player_test.rb
CHANGED
@@ -1,12 +1,51 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
class PlayerTest <
|
4
|
-
include FlexMock::TestCase
|
5
|
-
|
3
|
+
class PlayerTest < Minitest::Test
|
6
4
|
def setup
|
7
5
|
@player = Noplayer.new
|
8
6
|
end
|
9
7
|
|
8
|
+
# Default name
|
9
|
+
|
10
|
+
def test_default_name
|
11
|
+
assert_equal "Noplayer", @player.name
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_default_name_should_remove_namespace
|
15
|
+
flexmock(@player).should_receive(:class).and_return("Foo::Bar")
|
16
|
+
assert_equal "Bar", @player.name
|
17
|
+
end
|
18
|
+
|
19
|
+
# Default paused?
|
20
|
+
|
21
|
+
def test_paused_is_false_if_not_playing
|
22
|
+
flexmock(@player).should_receive(:playing?).once.and_return(false)
|
23
|
+
assert @player.paused?
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_paused_is_true_if_not_paused
|
27
|
+
flexmock(@player).should_receive(:playing?).once.and_return(true)
|
28
|
+
assert !@player.paused?
|
29
|
+
end
|
30
|
+
|
31
|
+
# Default playpause
|
32
|
+
|
33
|
+
def test_playpause_toggles_play
|
34
|
+
flexmock(@player).should_receive(:paused?).once.and_return(true)
|
35
|
+
flexmock(@player).should_receive(:play).once
|
36
|
+
|
37
|
+
@player.playpause
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_playpause_toggles_pause
|
41
|
+
flexmock(@player).should_receive(:paused?).once.and_return(false)
|
42
|
+
flexmock(@player).should_receive(:pause).once
|
43
|
+
|
44
|
+
@player.playpause
|
45
|
+
end
|
46
|
+
|
47
|
+
# Votes
|
48
|
+
|
10
49
|
def test_votes
|
11
50
|
Player::DEFAULT_VOTES_TO_SKIP.times do |i|
|
12
51
|
@player.vote
|
@@ -16,7 +55,7 @@ class PlayerTest < MiniTest::Unit::TestCase
|
|
16
55
|
assert_equal @player.votes, 0
|
17
56
|
else
|
18
57
|
assert_equal @player.votes, i + 1
|
19
|
-
|
58
|
+
end
|
20
59
|
end
|
21
60
|
end
|
22
61
|
|
@@ -45,9 +84,7 @@ class PlayerTest < MiniTest::Unit::TestCase
|
|
45
84
|
assert_equal @player.votes, 0
|
46
85
|
else
|
47
86
|
assert_equal @player.votes, i + 1
|
48
|
-
|
87
|
+
end
|
49
88
|
end
|
50
89
|
end
|
51
|
-
|
52
|
-
|
53
90
|
end
|