anyplayer 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
+ gem "rake"
4
+
3
5
  # Gem dependencies in anyplayer.gemspec
4
6
  gemspec
5
7
 
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ anyplayer (0.0.2)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ minitest (4.1.0)
10
+ rake (0.9.2.2)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ anyplayer!
17
+ minitest
18
+ rake
data/Rakefile CHANGED
@@ -1,2 +1,11 @@
1
1
  require 'bundler'
2
+ require 'rake/testtask'
3
+
2
4
  Bundler::GemHelper.install_tasks
5
+
6
+ task :default => :test
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.pattern = "test/*_test.rb"
10
+ t.verbose = true
11
+ end
@@ -1,12 +1,71 @@
1
1
  Anyplayer
2
2
  =========
3
3
 
4
- Ruby library to interact with the running music player (iTunes, Rythmbox, MPD, XMMS).
4
+ Interacts with the currently running music player. Supports iTunes OS X, iTunes Windows,
5
+ Rythmbox, MPD & XMMS2.
5
6
 
6
- require 'anyplayer'
7
- player = Anyplayer::launched
8
- player.name # => Rythmbox
9
- player.track # => "Frontier Psychiatrist"
10
- player.next
11
- player.track # => "Ready For The Floor"
7
+ Install
8
+ -------
12
9
 
10
+ ```sh
11
+ $ gem install anyplayer
12
+ ```
13
+
14
+ Use it in your terminal
15
+ -----------------------
16
+
17
+ ```sh
18
+ $ anyplayer artist # artist of the current track
19
+ New Order
20
+ $ anyplayer track # name of the current track
21
+ Blue Monday
22
+ $ anyplayer album
23
+ Power, Corruption & Lies
24
+ $ anyplayer next # changes track forward
25
+ $ anyplayer prev # backward
26
+ $ anyplayer playpause # pauses if it is playing, plays if it's paused
27
+ $ anyplayer play
28
+ $ anyplayer pause
29
+ $ anyplayer voldown # put the volume somewhat up
30
+ $ anyplayer volup # down
31
+ $ anyplayer volume # prints the volume percentage
32
+ 100
33
+ $ anyplayer vote # votes to go to next song (default number of votes is 5)
34
+ $ anyplayer name
35
+ iTunes
36
+ $ anyplayer launched && echo "a player is running" || echo "nothing running"
37
+ a player is running
38
+ ```
39
+
40
+ Or in Ruby
41
+ ----------
42
+
43
+ ```ruby
44
+ require 'anyplayer'
45
+ player = Anyplayer::launched
46
+
47
+ player.launched? # => true
48
+ player.name # => Rythmbox
49
+ player.artist # => "The Avalanches"
50
+ player.track # => "Frontier Psychiatrist"
51
+ # …
52
+ ```
53
+
54
+ Or in a browser
55
+ ----------------
56
+
57
+ With the [So Nice](https://github.com/sunny/so-nice/) Web interface:
58
+
59
+ ![So Nice Screenshot](https://github.com/sunny/so-nice/raw/gh-pages/screenshot.png)
60
+
61
+ Development
62
+ -----------
63
+
64
+ Launch from source:
65
+
66
+ ruby -Ilib bin/anyplayer
67
+
68
+ Install from source:
69
+
70
+ gem build anyplayer.gemspec
71
+ gem install anyplayer-*.gem
@@ -6,8 +6,8 @@ Gem::Specification.new do |s|
6
6
  s.name = "anyplayer"
7
7
  s.version = Anyplayer::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
- s.authors = ["Sunny Ripert"]
10
- s.email = ["sunny@sunfox.org"]
9
+ s.authors = ["Sunny Ripert", "Gordon Diggs"]
10
+ s.email = ["sunny@sunfox.org", "gordon@gordondiggs.com"]
11
11
  s.homepage = "http://github.com/sunny/anyplayer"
12
12
  s.summary = %q{Interact with the running music player}
13
13
  s.description = %q{Play/pause/skip songs in iTunes, Rythmbox, MPD, XMMS}
@@ -16,4 +16,6 @@ Gem::Specification.new do |s|
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency 'minitest'
19
21
  end
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding: utf-8 -*-
3
+ require 'anyplayer'
4
+
5
+ player = Anyplayer::launched
6
+
7
+ if !player
8
+ puts "Error: no player connected."
9
+ exit 1
10
+ end
11
+
12
+ case ARGV.first
13
+ when "playpause" then player.playpause
14
+ when "play" then player.play
15
+ when "pause" then palyer.pause
16
+ when "next" then player.next
17
+ when "prev" then player.next
18
+ when "voldown" then player.voldown
19
+ when "volup" then player.volup
20
+ when "volume" then puts player.volume
21
+ when "track" then puts player.track
22
+ when "artist" then puts player.artist
23
+ when "album" then puts player.album
24
+ when "vote" then player.vote
25
+ when "name" then puts player.name
26
+ when "launched" then exit(player.launched? ? 0 : 1)
27
+ when "playing" then exit(player.playing? ? 0 : 1)
28
+ when "paused" then exit(player.playing? ? 0 : 1)
29
+ else
30
+ puts <<USAGE
31
+ Usage: #{$0} [command]
32
+
33
+ Where command is one of: playpause, play, pause, next, prev, voldown, volup,
34
+ volume, track, artist, album, vote, name, launched.
35
+
36
+ Player connected: #{player.name}.
37
+ USAGE
38
+ exit(1)
39
+ end
@@ -2,7 +2,7 @@ require "timeout"
2
2
  require "anyplayer/player"
3
3
 
4
4
  module Anyplayer
5
- PLAYERS = :itunes, :rhythmbox, :ituneswindows, :mpd, :xmms2, :amarok
5
+ PLAYERS = [:itunes, :rhythmbox, :ituneswindows, :mpd, :xmms2, :amarok]
6
6
  for player in PLAYERS
7
7
  require "anyplayer/players/#{player}"
8
8
  end
@@ -1,22 +1,68 @@
1
+ # Default Player class that is inherrited by all players.
2
+ #
3
+ # All players should override these methods:
4
+ # launched? (return bool)
5
+ # next
6
+ # prev
7
+ # play
8
+ # pause
9
+ # playpause
10
+ # track (return string)
11
+ # artist (return string)
12
+ # album (return string)
13
+ # voldown
14
+ # volup
15
+ # volume (return int)
16
+ # playing? (return bool)
17
+ # paused? (return bool)
1
18
  module Anyplayer
2
19
  class Player
20
+ DEFAULT_VOTES_TO_SKIP = 5
3
21
 
4
- # Guess the player name
22
+ def initialize
23
+ @votes = 0
24
+ end
25
+
26
+ def launched?
27
+ false
28
+ end
29
+
30
+ # Player name is the classe's, feel free to override it
5
31
  def name
6
32
  self.class.to_s.gsub(/^.*::/, '')
7
33
  end
8
34
 
9
- # Methods to override
10
- def launched?; false; end
11
- def playpause; end
12
- def next; end
13
- def prev; end
14
- def voldown; end
15
- def volup; end
16
- def volume; end
17
- def track; end
18
- def artist; end
19
- def album; end
35
+ def playpause
36
+ paused? ? play : pause
37
+ end
38
+
39
+ # Vote to skip song
40
+ def vote(votes_to_skip = DEFAULT_VOTES_TO_SKIP)
41
+ @votes += 1
42
+ if @votes >= votes_to_skip
43
+ self.next
44
+ reset_votes
45
+ end
46
+ end
47
+
48
+ def votes
49
+ @votes
50
+ end
51
+
52
+ # Root next and prev reset the votes, so be sure to call super
53
+ # in children
54
+ def next
55
+ reset_votes
56
+ end
57
+
58
+ def prev
59
+ reset_votes
60
+ end
61
+
62
+ private
63
+ def reset_votes
64
+ @votes = 0
65
+ end
20
66
 
21
67
  end
22
68
  end
@@ -4,12 +4,22 @@ module Anyplayer
4
4
  tell_to 'PlayPause'
5
5
  end
6
6
 
7
+ def play
8
+ tell_to 'Play'
9
+ end
10
+
11
+ def pause
12
+ tell_to 'Pause'
13
+ end
14
+
7
15
  def prev
8
16
  tell_to 'Prev'
17
+ super
9
18
  end
10
19
 
11
20
  def next
12
21
  tell_to 'Next'
22
+ super
13
23
  end
14
24
 
15
25
  def voldown
@@ -27,17 +37,17 @@ module Anyplayer
27
37
  def track
28
38
  get_metadata('title')
29
39
  end
30
-
40
+
31
41
  def artist
32
42
  get_metadata('artist')
33
43
  end
34
-
44
+
35
45
  def album
36
46
  get_metadata('album')
37
47
  end
38
48
 
39
49
  def launched?
40
- not %x(qdbus org.kde.amarok 2>&1).match(/does not exist/)
50
+ not %x(qdbus org.kde.amarok 2>&1).match(/does not exist|command not found/)
41
51
  end
42
52
 
43
53
  private
@@ -1,55 +1,66 @@
1
+ if RUBY_PLATFORM =~ /darwin/
2
+ require 'appscript'
3
+ include Appscript
4
+ end
5
+
1
6
  module Anyplayer
2
7
  class Itunes < Player
3
8
  def playpause
4
- tell_to 'playpause'
9
+ @app.playpause
10
+ end
11
+
12
+ def play
13
+ @app.play
14
+ end
15
+
16
+ def pause
17
+ @app.pause
5
18
  end
6
19
 
7
20
  def prev
8
- tell_to 'previous track'
21
+ @app.previous_track
22
+ super
9
23
  end
10
24
 
11
25
  def next
12
- tell_to 'next track'
26
+ @app.next_track
27
+ super
13
28
  end
14
29
 
15
30
  def voldown
16
- tell_to 'set sound volume to sound volume - 10'
31
+ @app.sound_volume.set(volume + 10)
17
32
  end
18
33
 
19
34
  def volup
20
- tell_to 'set sound volume to sound volume + 10'
35
+ @app.sound_volume.set(volume + 10)
21
36
  end
22
37
 
23
38
  def volume
24
- tell_to 'return sound volume'
39
+ @app.sound_volume.get
25
40
  end
26
41
 
27
42
  def track
28
- tell_to 'return name of current track'
43
+ @app.current_track.name.get
29
44
  end
30
45
 
31
46
  def artist
32
- tell_to 'return artist of current track'
47
+ @app.current_track.artist.get
33
48
  end
34
49
 
35
50
  def album
36
- tell_to 'return album of current track'
51
+ @app.current_track.album.get
37
52
  end
38
53
 
39
54
  def launched?
40
- return false if RUBY_PLATFORM !~ /darwin/
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
55
+ return false unless RUBY_PLATFORM =~ /darwin/
56
+ return false unless app('System Events').processes.name.get.include? "iTunes"
57
+ @app = app('iTunes')
58
+ true
43
59
  end
44
60
 
45
61
  def name
46
62
  "iTunes"
47
63
  end
48
-
49
- private
50
- def tell_to(command)
51
- %x(osascript -e 'tell app "iTunes" to #{command}').rstrip
52
- end
53
64
  end
54
65
  end
55
66
 
@@ -4,12 +4,22 @@ module Anyplayer
4
4
  @itunes.PlayPause()
5
5
  end
6
6
 
7
+ def play
8
+ @itunes.Play()
9
+ end
10
+
11
+ def pause
12
+ @itunes.Pause()
13
+ end
14
+
7
15
  def prev
8
16
  @itunes.PreviousTrack()
17
+ super
9
18
  end
10
19
 
11
20
  def next
12
21
  @itunes.NextTrack()
22
+ super
13
23
  end
14
24
 
15
25
  def voldown
@@ -4,12 +4,22 @@ module Anyplayer
4
4
  mpc 'toggle'
5
5
  end
6
6
 
7
+ def play
8
+ mpc 'play'
9
+ end
10
+
11
+ def pause
12
+ mpc 'pause'
13
+ end
14
+
7
15
  def prev
8
16
  mpc 'prev'
17
+ super
9
18
  end
10
19
 
11
20
  def next
12
21
  mpc 'next'
22
+ super
13
23
  end
14
24
 
15
25
  def voldown
@@ -4,12 +4,22 @@ module Anyplayer
4
4
  tell_to 'play-pause'
5
5
  end
6
6
 
7
+ def play
8
+ tell_to 'play'
9
+ end
10
+
11
+ def pause
12
+ tell_to 'pause'
13
+ end
14
+
7
15
  def prev
8
16
  tell_to 'previous'
17
+ super
9
18
  end
10
19
 
11
20
  def next
12
21
  tell_to 'next'
22
+ super
13
23
  end
14
24
 
15
25
  def voldown
@@ -31,7 +41,7 @@ module Anyplayer
31
41
  def artist
32
42
  tell_to 'print-playing-format=%ta'
33
43
  end
34
-
44
+
35
45
  def album
36
46
  tell_to 'print-playing-format=%at'
37
47
  end
@@ -4,12 +4,22 @@ module Anyplayer
4
4
  xmms2 'toggle'
5
5
  end
6
6
 
7
+ def play
8
+ xmms2 'play'
9
+ end
10
+
11
+ def pause
12
+ xmms2 'pause'
13
+ end
14
+
7
15
  def prev
8
16
  xmms2 'prev'
17
+ super
9
18
  end
10
19
 
11
20
  def next
12
21
  xmms2 'next'
22
+ super
13
23
  end
14
24
 
15
25
  def voldown
@@ -25,8 +35,8 @@ module Anyplayer
25
35
  end
26
36
 
27
37
  def volume
28
- #currently just the first (left?) channel
29
- xmms2('server volume').split("\n").first.sub /([^0-9]*)/, ''
38
+ # currently just the first (left?) channel
39
+ xmms2('server volume').split("\n").first.sub(/([^0-9]*)/, '')
30
40
  $1
31
41
  end
32
42
 
@@ -42,6 +52,14 @@ module Anyplayer
42
52
  xmms2 "status -f '${album}'"
43
53
  end
44
54
 
55
+ def playing?
56
+ xmms2("status -f '${playback_status}'") == "Playing"
57
+ end
58
+
59
+ def paused?
60
+ xmms2("status -f '${playback_status}'") == "Paused"
61
+ end
62
+
45
63
  def launched?
46
64
  # xmms2 autolaunches the daemon, so this should always be true
47
65
  %x(xmms2 status 2> /dev/null)
@@ -54,8 +72,8 @@ module Anyplayer
54
72
 
55
73
  private
56
74
  def xmms2(command)
57
- %x(xmms2 #{command}).split("\n").first
75
+ %x(xmms2 #{command}).split("\n").first.strip
58
76
  end
59
77
  end
60
78
 
61
- end
79
+ end
@@ -1,3 +1,3 @@
1
1
  module Anyplayer
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,13 +1,75 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- $LOAD_PATH.unshift(File.dirname(__FILE__))
1
+ require "minitest/unit"
2
+ require "minitest/autorun"
3
+ require "anyplayer"
3
4
 
4
- require 'test/unit'
5
- require 'anyplayer'
5
+ class AnyplayerTest < MiniTest::Unit::TestCase
6
+ def setup
7
+ @player = Anyplayer::launched
8
+ refute_nil @player, "Make sure you have launched a player for tests to run"
9
+ end
6
10
 
7
- class AnyplayerTest < Test::Unit::TestCase
8
11
  def test_music_player_running
9
- player = Anyplayer::launched
10
- assert_not_nil player
11
- assert player.is_a?(Anyplayer::Player)
12
+ assert_kind_of Anyplayer::Player, @player
13
+ end
14
+
15
+
16
+ def test_voting
17
+ assert_equal @player.votes, 0
18
+
19
+ first_track = @player.track
20
+
21
+ Anyplayer::Player::DEFAULT_VOTES_TO_SKIP.times do |i|
22
+ @player.vote
23
+
24
+ # votes should be 0 if we've voted enough times
25
+ if i == Anyplayer::Player::DEFAULT_VOTES_TO_SKIP-1
26
+ assert_equal @player.votes, 0
27
+ else
28
+ assert_equal @player.votes, i+1
29
+ end
30
+ end
31
+
32
+ # make sure we actually changed tracks
33
+ refute_equal @player.track, first_track
34
+
35
+ # rewind test
36
+ @player.prev
37
+ @player.play
38
+ end
39
+
40
+ def test_vote_resets
41
+ assert_equal @player.votes, 0
42
+
43
+ @player.next
44
+ assert_equal @player.votes, 0
45
+
46
+ @player.prev
47
+ assert_equal @player.votes, 0
48
+ end
49
+
50
+ def test_custom_voting_quota
51
+ assert_equal @player.votes, 0
52
+
53
+ num_votes = 10
54
+
55
+ first_track = @player.track
56
+
57
+ num_votes.times do |i|
58
+ @player.vote(num_votes)
59
+
60
+ # votes should be 0 if we've voted enough times
61
+ if i == num_votes-1
62
+ assert_equal @player.votes, 0
63
+ else
64
+ assert_equal @player.votes, i+1
65
+ end
66
+ end
67
+
68
+ # make sure we actually changed tracks
69
+ refute_equal @player.track, first_track
70
+
71
+ # rewind test
72
+ @player.prev
73
+ @player.play
12
74
  end
13
75
  end
metadata CHANGED
@@ -1,39 +1,50 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: anyplayer
3
- version: !ruby/object:Gem::Version
4
- hash: 29
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Sunny Ripert
9
+ - Gordon Diggs
14
10
  autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
-
18
- date: 2011-01-18 00:00:00 +01:00
19
- default_executable:
20
- dependencies: []
21
-
13
+ date: 2013-01-22 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: minitest
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
22
31
  description: Play/pause/skip songs in iTunes, Rythmbox, MPD, XMMS
23
- email:
32
+ email:
24
33
  - sunny@sunfox.org
25
- executables: []
26
-
34
+ - gordon@gordondiggs.com
35
+ executables:
36
+ - anyplayer
27
37
  extensions: []
28
-
29
38
  extra_rdoc_files: []
30
-
31
- files:
39
+ files:
32
40
  - .gitignore
41
+ - .travis.yml
33
42
  - Gemfile
43
+ - Gemfile.lock
34
44
  - Rakefile
35
45
  - Readme.markdown
36
46
  - anyplayer.gemspec
47
+ - bin/anyplayer
37
48
  - lib/anyplayer.rb
38
49
  - lib/anyplayer/player.rb
39
50
  - lib/anyplayer/players/amarok.rb
@@ -44,39 +55,29 @@ files:
44
55
  - lib/anyplayer/players/xmms2.rb
45
56
  - lib/anyplayer/version.rb
46
57
  - test/anyplayer_test.rb
47
- has_rdoc: true
48
58
  homepage: http://github.com/sunny/anyplayer
49
59
  licenses: []
50
-
51
60
  post_install_message:
52
61
  rdoc_options: []
53
-
54
- require_paths:
62
+ require_paths:
55
63
  - lib
56
- required_ruby_version: !ruby/object:Gem::Requirement
64
+ required_ruby_version: !ruby/object:Gem::Requirement
57
65
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 3
62
- segments:
63
- - 0
64
- version: "0"
65
- required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
71
  none: false
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- hash: 3
71
- segments:
72
- - 0
73
- version: "0"
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
74
76
  requirements: []
75
-
76
77
  rubyforge_project:
77
- rubygems_version: 1.3.7
78
+ rubygems_version: 1.8.23
78
79
  signing_key:
79
80
  specification_version: 3
80
81
  summary: Interact with the running music player
81
- test_files: []
82
-
82
+ test_files:
83
+ - test/anyplayer_test.rb