anyplayer 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -0
- data/Gemfile.lock +3 -1
- data/Rakefile +1 -0
- data/Readme.markdown +17 -5
- data/anyplayer.gemspec +1 -0
- data/bin/anyplayer +13 -8
- data/lib/anyplayer.rb +17 -18
- data/lib/anyplayer/player.rb +45 -39
- data/lib/anyplayer/players/amarok.rb +43 -45
- data/lib/anyplayer/players/itunes_mac.rb +53 -0
- data/lib/anyplayer/players/itunes_windows.rb +68 -0
- data/lib/anyplayer/players/mpd.rb +45 -47
- data/lib/anyplayer/players/noplayer.rb +45 -0
- data/lib/anyplayer/players/rhythmbox.rb +41 -43
- data/lib/anyplayer/players/xmms2.rb +58 -60
- data/lib/anyplayer/selector.rb +66 -0
- data/lib/anyplayer/version.rb +1 -1
- data/test/anyplayer_test.rb +10 -69
- data/test/player_test.rb +53 -0
- data/test/selector_test.rb +26 -0
- data/test/test_helper.rb +9 -0
- metadata +34 -4
- data/lib/anyplayer/players/itunes.rb +0 -66
- data/lib/anyplayer/players/ituneswindows.rb +0 -66
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
anyplayer (0.0.
|
4
|
+
anyplayer (0.0.3)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
|
+
flexmock (0.9.0)
|
9
10
|
minitest (4.1.0)
|
10
11
|
rake (0.9.2.2)
|
11
12
|
|
@@ -14,5 +15,6 @@ PLATFORMS
|
|
14
15
|
|
15
16
|
DEPENDENCIES
|
16
17
|
anyplayer!
|
18
|
+
flexmock
|
17
19
|
minitest
|
18
20
|
rake
|
data/Rakefile
CHANGED
data/Readme.markdown
CHANGED
@@ -42,7 +42,7 @@ Or in Ruby
|
|
42
42
|
|
43
43
|
```ruby
|
44
44
|
require 'anyplayer'
|
45
|
-
player = Anyplayer::
|
45
|
+
player = Anyplayer::Selector.new.player
|
46
46
|
|
47
47
|
player.launched? # => true
|
48
48
|
player.name # => Rythmbox
|
@@ -58,14 +58,26 @@ With the [So Nice](https://github.com/sunny/so-nice/) Web interface:
|
|
58
58
|
|
59
59
|
![So Nice Screenshot](https://github.com/sunny/so-nice/raw/gh-pages/screenshot.png)
|
60
60
|
|
61
|
+
|
61
62
|
Development
|
62
63
|
-----------
|
63
64
|
|
64
|
-
|
65
|
+
Depending on your configuration you may need to add `bundle exec` to the following commands.
|
66
|
+
|
67
|
+
Terminal binary from source:
|
68
|
+
|
69
|
+
```sh
|
70
|
+
$ ruby -Ilib bin/anyplayer
|
71
|
+
```
|
72
|
+
|
73
|
+
Tests:
|
65
74
|
|
66
|
-
|
75
|
+
```sh
|
76
|
+
$ rake test
|
77
|
+
```
|
67
78
|
|
68
79
|
Install from source:
|
69
80
|
|
70
|
-
|
71
|
-
|
81
|
+
```sh
|
82
|
+
$ rake install
|
83
|
+
```
|
data/anyplayer.gemspec
CHANGED
data/bin/anyplayer
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# -*- encoding: utf-8 -*-
|
3
|
-
require 'anyplayer'
|
4
2
|
|
5
|
-
|
3
|
+
require 'anyplayer'
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
# Create a selector
|
6
|
+
selector = Anyplayer::Selector.new
|
7
|
+
if ARGV.first == "-v"
|
8
|
+
selector.verbose = true
|
9
|
+
ARGV.pop
|
10
10
|
end
|
11
11
|
|
12
|
+
# Find the current player
|
13
|
+
player = selector.player
|
14
|
+
abort "Error: no player connected.\n" + selector.errors.join("\n") if !player
|
15
|
+
|
16
|
+
# Call it
|
12
17
|
case ARGV.first
|
13
18
|
when "playpause" then player.playpause
|
14
19
|
when "play" then player.play
|
@@ -28,7 +33,7 @@ case ARGV.first
|
|
28
33
|
when "paused" then exit(player.playing? ? 0 : 1)
|
29
34
|
else
|
30
35
|
puts <<USAGE
|
31
|
-
Usage: #{$0} [command]
|
36
|
+
Usage: #{$0} [-v] [command]
|
32
37
|
|
33
38
|
Where command is one of: playpause, play, pause, next, prev, voldown, volup,
|
34
39
|
volume, track, artist, album, vote, name, launched.
|
@@ -36,4 +41,4 @@ volume, track, artist, album, vote, name, launched.
|
|
36
41
|
Player connected: #{player.name}.
|
37
42
|
USAGE
|
38
43
|
exit(1)
|
39
|
-
end
|
44
|
+
end
|
data/lib/anyplayer.rb
CHANGED
@@ -1,24 +1,23 @@
|
|
1
1
|
require "timeout"
|
2
|
-
require "anyplayer/player"
|
3
2
|
|
4
3
|
module Anyplayer
|
5
|
-
PLAYERS =
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
PLAYERS = %w(
|
5
|
+
rhythmbox
|
6
|
+
mpd
|
7
|
+
xmms2
|
8
|
+
amarok
|
9
|
+
itunes_mac
|
10
|
+
itunes_windows
|
11
|
+
spotify_mac
|
12
|
+
)
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
player = const_get(player.to_s.capitalize).new
|
14
|
-
puts "Trying #{player.name}..." if verbose
|
15
|
-
|
16
|
-
begin
|
17
|
-
Timeout::timeout(5) { return player if player.launched? }
|
18
|
-
rescue Timeout::Error
|
19
|
-
puts "Timed out" if verbose
|
20
|
-
end
|
21
|
-
}
|
22
|
-
nil
|
14
|
+
def self.launched
|
15
|
+
$stderr.puts "Anyplayer.launched is deprecated: please initialize a new Selector and call player"
|
16
|
+
Selector.new.player
|
23
17
|
end
|
24
18
|
end
|
19
|
+
|
20
|
+
require "anyplayer/player"
|
21
|
+
require "anyplayer/selector"
|
22
|
+
|
23
|
+
|
data/lib/anyplayer/player.rb
CHANGED
@@ -15,55 +15,61 @@
|
|
15
15
|
# volume (return int)
|
16
16
|
# playing? (return bool)
|
17
17
|
# paused? (return bool)
|
18
|
-
|
19
|
-
|
20
|
-
DEFAULT_VOTES_TO_SKIP = 5
|
18
|
+
class Anyplayer::Player
|
19
|
+
DEFAULT_VOTES_TO_SKIP = 5
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def launched?
|
27
|
-
false
|
28
|
-
end
|
29
|
-
|
30
|
-
# Player name is the classe's, feel free to override it
|
31
|
-
def name
|
32
|
-
self.class.to_s.gsub(/^.*::/, '')
|
33
|
-
end
|
21
|
+
def initialize
|
22
|
+
@votes = 0
|
23
|
+
end
|
34
24
|
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
# Return true if the player is currently launched
|
26
|
+
def launched?
|
27
|
+
false
|
28
|
+
end
|
38
29
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
end
|
30
|
+
# Player name defaults to the classe's, feel free to override it
|
31
|
+
# Example:
|
32
|
+
# player.name # => iTunes
|
33
|
+
def name
|
34
|
+
self.class.to_s.gsub(/^.*::/, '')
|
35
|
+
end
|
47
36
|
|
48
|
-
|
49
|
-
|
50
|
-
|
37
|
+
# Tells the player to toggle the pause state
|
38
|
+
def playpause
|
39
|
+
paused? ? play : pause
|
40
|
+
end
|
51
41
|
|
52
|
-
|
53
|
-
|
54
|
-
|
42
|
+
# Vote to skip this song
|
43
|
+
def vote(votes_to_skip = DEFAULT_VOTES_TO_SKIP)
|
44
|
+
@votes += 1
|
45
|
+
if @votes >= votes_to_skip
|
46
|
+
self.next
|
55
47
|
reset_votes
|
56
48
|
end
|
49
|
+
end
|
57
50
|
|
58
|
-
|
59
|
-
|
60
|
-
|
51
|
+
# Returns the number of votes to skip this song
|
52
|
+
def votes
|
53
|
+
@votes
|
54
|
+
end
|
61
55
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
56
|
+
# Tell the player to go the the next song
|
57
|
+
# This resets the votes, so be sure to call super in children
|
58
|
+
def next
|
59
|
+
reset_votes
|
60
|
+
end
|
66
61
|
|
62
|
+
# Tell the player to go to the previous song
|
63
|
+
# This resets the votes, so be sur eto call super in children
|
64
|
+
def prev
|
65
|
+
reset_votes
|
67
66
|
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def reset_votes
|
71
|
+
@votes = 0
|
72
|
+
end
|
73
|
+
|
68
74
|
end
|
69
75
|
|
@@ -1,63 +1,61 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
1
|
+
class Anyplayer::Amarok < Anyplayer::Player
|
2
|
+
def playpause
|
3
|
+
amarok 'PlayPause'
|
4
|
+
end
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def play
|
7
|
+
amarok 'Play'
|
8
|
+
end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
def pause
|
11
|
+
amarok 'Pause'
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
def prev
|
15
|
+
amarok 'Prev'
|
16
|
+
super
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
def next
|
20
|
+
amarok 'Next'
|
21
|
+
super
|
22
|
+
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def voldown
|
25
|
+
amarok 'VolumeDown 5'
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
def volup
|
29
|
+
amarok 'VolumeUp 5'
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
def volume
|
33
|
+
amarok 'VolumeGet'
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
def track
|
37
|
+
amarok_get_meta 'title'
|
38
|
+
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
def artist
|
41
|
+
amarok_get_meta 'artist'
|
42
|
+
end
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
def album
|
45
|
+
amarok_get_meta 'album'
|
46
|
+
end
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
def launched?
|
49
|
+
not %x(qdbus org.kde.amarok 2>&1).match(/does not exist|command not found/)
|
50
|
+
end
|
52
51
|
|
53
|
-
|
54
|
-
def
|
52
|
+
private
|
53
|
+
def amarok(command)
|
55
54
|
%x(qdbus org.kde.amarok /Player org.freedesktop.MediaPlayer.#{command}).rstrip
|
56
55
|
end
|
57
56
|
|
58
|
-
def
|
59
|
-
|
57
|
+
def amarok_get_meta(name)
|
58
|
+
amarok('GetMetadata').match(/#{name}: (\S.*)/)[1] rescue nil
|
60
59
|
end
|
61
|
-
end
|
62
60
|
end
|
63
61
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Anyplayer::ItunesMac < Anyplayer::Player
|
2
|
+
def playpause
|
3
|
+
itunes 'playpause'
|
4
|
+
end
|
5
|
+
|
6
|
+
def prev
|
7
|
+
itunes 'previous track'
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def next
|
12
|
+
itunes 'next track'
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def voldown
|
17
|
+
itunes 'set sound volume to sound volume - 10'
|
18
|
+
end
|
19
|
+
|
20
|
+
def volup
|
21
|
+
itunes 'set sound volume to sound volume + 10'
|
22
|
+
end
|
23
|
+
|
24
|
+
def volume
|
25
|
+
itunes 'return sound volume'
|
26
|
+
end
|
27
|
+
|
28
|
+
def track
|
29
|
+
itunes 'return name of current track'
|
30
|
+
end
|
31
|
+
|
32
|
+
def artist
|
33
|
+
itunes 'return artist of current track'
|
34
|
+
end
|
35
|
+
|
36
|
+
def album
|
37
|
+
itunes 'return album of current track'
|
38
|
+
end
|
39
|
+
|
40
|
+
def launched?
|
41
|
+
nb = %x(osascript -e 'tell app "System Events" to count (every process whose name is "iTunes")' 2>/dev/null).rstrip
|
42
|
+
nb.match(/^\d+/) and nb.to_i > 0 ? true : false
|
43
|
+
end
|
44
|
+
|
45
|
+
def name
|
46
|
+
"iTunes Mac"
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def itunes(command)
|
51
|
+
%x(osascript -e 'tell app "iTunes" to #{command}').rstrip
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
begin
|
2
|
+
require 'win32ole'
|
3
|
+
rescue LoadError => e
|
4
|
+
raise LoadError.new("#{e.message} -- You probably aren't on Windows")
|
5
|
+
end
|
6
|
+
|
7
|
+
class Anyplayer::ItunesWindows < Anyplayer::Player
|
8
|
+
def playpause
|
9
|
+
itunes.PlayPause()
|
10
|
+
end
|
11
|
+
|
12
|
+
def play
|
13
|
+
itunes.Play()
|
14
|
+
end
|
15
|
+
|
16
|
+
def pause
|
17
|
+
itunes.Pause()
|
18
|
+
end
|
19
|
+
|
20
|
+
def prev
|
21
|
+
itunes.PreviousTrack()
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def next
|
26
|
+
itunes.NextTrack()
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def voldown
|
31
|
+
itunes.SoundVolume = itunes.SoundVolume - 10
|
32
|
+
end
|
33
|
+
|
34
|
+
def volup
|
35
|
+
itunes.SoundVolume = itunes.SoundVolume + 10
|
36
|
+
end
|
37
|
+
|
38
|
+
def volume
|
39
|
+
itunes.SoundVolume
|
40
|
+
end
|
41
|
+
|
42
|
+
def track
|
43
|
+
itunes.CurrentTrack.name
|
44
|
+
end
|
45
|
+
|
46
|
+
def artist
|
47
|
+
itunes.CurrentTrack.Artist
|
48
|
+
end
|
49
|
+
|
50
|
+
def album
|
51
|
+
itunes.CurrentTrack.Album
|
52
|
+
end
|
53
|
+
|
54
|
+
def launched?
|
55
|
+
itunes
|
56
|
+
end
|
57
|
+
|
58
|
+
def name
|
59
|
+
"iTunes Windows"
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def itunes
|
65
|
+
itunes ||= WIN32OLE.new("iTunes.Application")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|