hearken 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +1 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +2 -4
  4. data/README.rdoc +48 -0
  5. data/Rakefile +5 -0
  6. data/bin/hearken +7 -0
  7. data/hearken.gemspec +9 -0
  8. data/lib/hearken.rb +1 -5
  9. data/lib/hearken/cli.rb +24 -0
  10. data/lib/hearken/command.rb +35 -0
  11. data/lib/hearken/command/enqueue.rb +12 -0
  12. data/lib/hearken/command/flush.rb +7 -0
  13. data/lib/hearken/command/list.rb +29 -0
  14. data/lib/hearken/command/recent.rb +31 -0
  15. data/lib/hearken/command/reload.rb +7 -0
  16. data/lib/hearken/command/restart.rb +7 -0
  17. data/lib/hearken/command/scrobbling.rb +14 -0
  18. data/lib/hearken/command/search.rb +25 -0
  19. data/lib/hearken/command/setup_scrobbling.rb +7 -0
  20. data/lib/hearken/command/show_properties.rb +9 -0
  21. data/lib/hearken/command/shuffle.rb +13 -0
  22. data/lib/hearken/command/start.rb +7 -0
  23. data/lib/hearken/command/status.rb +7 -0
  24. data/lib/hearken/command/stop.rb +7 -0
  25. data/lib/hearken/console.rb +34 -0
  26. data/lib/hearken/debug.rb +16 -0
  27. data/lib/hearken/indexing.rb +7 -0
  28. data/lib/hearken/indexing/audio_traverser.rb +19 -0
  29. data/lib/hearken/indexing/executor.rb +33 -0
  30. data/lib/hearken/indexing/ffmpeg_file.rb +51 -0
  31. data/lib/hearken/indexing/file.rb +13 -0
  32. data/lib/hearken/indexing/indexer.rb +28 -0
  33. data/lib/hearken/indexing/parser.rb +7 -0
  34. data/lib/hearken/indexing/persistant_traverser.rb +32 -0
  35. data/lib/hearken/indexing/persisted_traverser.rb +30 -0
  36. data/lib/hearken/library.rb +46 -0
  37. data/lib/hearken/player.rb +91 -0
  38. data/lib/hearken/preferences.rb +29 -0
  39. data/lib/hearken/queue.rb +26 -0
  40. data/lib/hearken/range_expander.rb +30 -0
  41. data/lib/hearken/scrobbler.rb +76 -0
  42. data/lib/hearken/tagged.rb +15 -0
  43. data/lib/hearken/track.rb +38 -0
  44. data/lib/hearken/version.rb +2 -2
  45. data/media/applause.mp3 +0 -0
  46. data/spec/hearken/command/enqueue_spec.rb +24 -0
  47. data/spec/hearken/command/list_spec.rb +31 -0
  48. data/spec/hearken/command/reload_spec.rb +20 -0
  49. data/spec/hearken/command/shuffle_spec.rb +27 -0
  50. data/spec/hearken/player_spec.rb +37 -0
  51. data/spec/hearken/range_expander_spec.rb +28 -0
  52. data/spec/spec_helper.rb +5 -0
  53. metadata +136 -8
@@ -0,0 +1,76 @@
1
+ require 'splat'
2
+ require 'simple_scrobbler'
3
+ require 'hearken/debug'
4
+
5
+ module Hearken
6
+ class Scrobbler
7
+ include Debug
8
+
9
+ def initialize preferences
10
+ @preferences = preferences
11
+ if preferences['lastfm']
12
+ debug "Configuring scrobbler with #{preferences['lastfm'].inspect}"
13
+ @scrobbler = SimpleScrobbler.new *%w{api_key secret user session_key}.map{|k| preferences['lastfm'][k]}
14
+ end
15
+ end
16
+
17
+ def scrobble track
18
+ return unless @scrobbler
19
+ debug "Scrobbling to last fm: #{track}"
20
+ send_to_scrobbler :submit, track
21
+ end
22
+
23
+ def update track
24
+ return unless @scrobbler
25
+ debug "Updating now listening with last fm: #{track}"
26
+ send_to_scrobbler :now_playing, track
27
+ end
28
+
29
+ def ask question
30
+ print question
31
+ gets.chomp
32
+ end
33
+
34
+ def setup
35
+ puts <<-EOF
36
+ Because of the way lastfm authentication works, setting up lastfm involves two steps:
37
+ Firstly, you need to register that you are developing an application. This will give you an api key and an associated 'secret'
38
+ Secondly, you need to gives your application access your lastfm account. This will give a authenticated session.
39
+
40
+ Step 1. Logging in to your lastfm account and register an application
41
+ This will launch a browser. You need to log in and fill out the API registration form
42
+ EOF
43
+ answer = ask 'Are you ready ? '
44
+ return unless answer.downcase.start_with? 'y'
45
+ "http://www.last.fm/api/account".to_launcher
46
+ preferences = {}
47
+ preferences['api_key'] = ask 'What is your API key ? '
48
+ preferences['secret'] = ask 'What is your secret ? '
49
+ puts <<-EOF
50
+ Now you've got you application details, you need to create an authentication session between your application and your lastfm account
51
+ Step 2. Authorising your application to access your lastfm account
52
+ This will launch another browser. You just need to give your application permission to access your account
53
+ EOF
54
+ preferences['user'] = ask 'What is your lastfm user name ? '
55
+ @scrobbler = SimpleScrobbler.new preferences['api_key'], preferences['secret'], preferences['user']
56
+ preferences['session_key'] = @scrobbler.fetch_session_key do |url|
57
+ url.to_launcher
58
+ ask 'Hit enter when you\'ve allowed your application access to your account'
59
+ end
60
+ @preferences['lastfm'] = preferences
61
+ end
62
+ private
63
+ def send_to_scrobbler message, track
64
+ begin
65
+ debug %w{artist title time album track}.map {|k| "#{k}=#{track.send(k)}"}.join(',')
66
+ @scrobbler.send message, track.artist,
67
+ track.title,
68
+ :length => track.time,
69
+ :album => track.album,
70
+ :track_number => track.track
71
+ rescue Exception => e
72
+ puts "Failed to scrobble: #{e}"
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,15 @@
1
+ module Hearken::Tagged
2
+ FILE_FIELDS = %w{path timestamp}
3
+ TAG_FIELDS = %w{album track title artist time date albumartist puid mbartistid mbalbumid mbalbumartistid asin}
4
+ FIELDS = FILE_FIELDS + TAG_FIELDS
5
+
6
+ attr_accessor *FIELDS.map {|field| field.to_sym }
7
+
8
+ def no_tag_fields?
9
+ TAG_FIELDS.select {|field| send field }.empty?
10
+ end
11
+
12
+ def to_a
13
+ FIELDS.map { |field| send field }
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ require 'hearken/tagged'
2
+ require 'rainbow'
3
+
4
+ class Hearken::Track
5
+ include Hearken::Tagged
6
+ attr_accessor :id, :started
7
+
8
+ def initialize id=nil
9
+ @id = id
10
+ end
11
+
12
+ def [] key
13
+ self.send key
14
+ end
15
+
16
+ def valid?
17
+ @track
18
+ end
19
+
20
+ def search_id
21
+ id.to_s 36
22
+ end
23
+
24
+ def duration
25
+ end
26
+
27
+ def search_string
28
+ "#{self.artist.to_s.downcase}#{self.album.to_s.downcase}#{self.title.to_s.downcase}"
29
+ end
30
+
31
+ def to_s
32
+ "#{my(:search_id,:white)}: #{my(:artist, :yellow)} - #{my(:album,:cyan)} - #{my(:track,:magenta)} #{my(:title,:green)} (#{my(:time,:white)})"
33
+ end
34
+
35
+ def my field, colour
36
+ self.send(field).to_s.foreground(colour)
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Hearken
2
- VERSION = "0.0.1"
3
- end
2
+ VERSION = '0.0.2'
3
+ end
Binary file
@@ -0,0 +1,24 @@
1
+ require_relative '../../spec_helper'
2
+ require 'hearken/command/enqueue'
3
+
4
+ describe Hearken::Command::Enqueue do
5
+ extend ShellShock::CommandSpec
6
+
7
+ with_usage '*<id>'
8
+ with_help 'enqueues the list of songs with the specified ids'
9
+
10
+ before do
11
+ @player = stub('player')
12
+ @command = Hearken::Command::Enqueue.new @player
13
+ end
14
+
15
+ it 'should enqueue whatever is returned from the expander' do
16
+ expander = stub('expander')
17
+ Hearken::RangeExpander.should_receive(:new).and_return(expander)
18
+ expander.should_receive(:expand).with('some text').and_return([1,2,3])
19
+
20
+ [1,2,3].each {|id| @player.should_receive(:enqueue).with id}
21
+
22
+ @command.execute "some text"
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ require_relative '../../spec_helper'
2
+ require 'hearken/command/list'
3
+
4
+ describe Hearken::Command::List do
5
+ extend ShellShock::CommandSpec
6
+
7
+ with_help <<EOF
8
+ lists the contents of the track queue
9
+ these results can optionally be filtered by specified words
10
+ when playing, approximate times for each track will be displayed
11
+ EOF
12
+
13
+ before do
14
+ @player = stub('player')
15
+ @command = Hearken::Command::List.new @player
16
+ end
17
+
18
+ it 'should display nothing when there is no current track and nothing enqueued' do
19
+ @player.stub!(:current).and_return nil
20
+ @player.stub! :each
21
+ @command.execute ''
22
+ end
23
+
24
+ it 'should display queue contents with no times when there is no current track' do
25
+ track = stub 'track'
26
+ @player.stub!(:current).and_return nil
27
+ @player.stub!(:each).and_yield track
28
+ @command.should_receive(:puts).with track
29
+ @command.execute ''
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../../spec_helper'
2
+ require 'hearken/command/reload'
3
+
4
+ describe Hearken::Command::Reload do
5
+ extend ShellShock::CommandSpec
6
+
7
+ with_usage ''
8
+ with_help 'reloads the contents of the music library for fast searching'
9
+
10
+ before do
11
+ @library = stub('library')
12
+ @player = stub('player', :library => @library)
13
+ @command = Hearken::Command::Reload.new @player
14
+ end
15
+
16
+ it 'should reload the library' do
17
+ @library.should_receive(:reload)
18
+ @command.execute '123'
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../../spec_helper'
2
+ require 'hearken/command/shuffle'
3
+
4
+ describe Hearken::Command::Shuffle do
5
+ extend ShellShock::CommandSpec
6
+
7
+ with_usage ''
8
+ with_help 'shuffles the current queue'
9
+
10
+ before do
11
+ @player = stub 'player'
12
+ @command = Hearken::Command::Shuffle.new @player
13
+ end
14
+
15
+ it 'should dequeue all tracks, shuffle then enqueue them' do
16
+ @player.should_receive(:dequeue).and_return(1)
17
+ @player.should_receive(:dequeue).and_return(2)
18
+ @player.should_receive(:dequeue).and_return(3)
19
+ @player.should_receive(:dequeue).and_return nil
20
+
21
+ @player.should_receive(:enqueue).with 3
22
+ @player.should_receive(:enqueue).with 2
23
+ @player.should_receive(:enqueue).with 1
24
+
25
+ @command.execute
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ require_relative '../spec_helper'
2
+ require 'hearken/player'
3
+
4
+ describe Hearken::Player do
5
+ let(:preferences) { {} }
6
+ let(:player) { Hearken::Player.new preferences }
7
+
8
+ before do
9
+ scrobbler = mock 'scrobbler'
10
+ library = mock 'library'
11
+ Hearken::Scrobbler.stub!(:new).and_return scrobbler
12
+ Hearken::Library.stub!(:new).and_return library
13
+ library.stub! :reload
14
+ end
15
+
16
+ describe '#current' do
17
+ it 'should return current_track when player has pid and file is present' do
18
+ player.instance_eval { @pid = 1 }
19
+ hash = stub 'hash'
20
+ File.stub!(:exist?).with('current_song').and_return true
21
+ YAML.stub!(:load_file).with('current_song').and_return hash
22
+ player.current.should == hash
23
+ end
24
+
25
+ it 'should return nil when player has no pid and file is present' do
26
+ player.instance_eval { @pid = nil }
27
+ File.stub!(:exist?).with('current_song').and_return true
28
+ player.current.should == nil
29
+ end
30
+
31
+ it 'should return nil when has pid and file is not present' do
32
+ player.instance_eval { @pid = 1 }
33
+ File.stub!(:exist?).with('current_song').and_return false
34
+ player.current.should == nil
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ require_relative '../spec_helper'
2
+ require 'hearken/range_expander'
3
+
4
+ describe Hearken::RangeExpander do
5
+ before do
6
+ @expander = Hearken::RangeExpander.new
7
+ end
8
+
9
+ it 'should expand single values' do
10
+ @expander.expand('123').should == [1371]
11
+ end
12
+
13
+ it 'should expand multiple values separated by any non digit' do
14
+ @expander.expand("123 \t 456 , 789 ").should == [1371, 5370, 9369]
15
+ end
16
+
17
+ it 'should expand a fully specified range' do
18
+ @expander.expand(" 456-45i ").should == (5370..5382).to_a
19
+ end
20
+
21
+ it 'should expand an abbreviated range' do
22
+ @expander.expand(" 456-i ").should == (5370..5382).to_a
23
+ end
24
+
25
+ it 'should expand ids for a range' do
26
+ @expander.expand_to_ids(" s-z ").should == %w{s t u v w x y z}
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'bundler/setup'
4
+ require 'rspec'
5
+ require 'shell_shock/command_spec'
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: hearken
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mark Ryall
@@ -10,10 +10,86 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-07-04 00:00:00 +10:00
13
+ date: 2011-07-05 00:00:00 +10:00
14
14
  default_executable:
15
- dependencies: []
16
-
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: thor
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: splat
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: shell_shock
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: simple_scrobbler
51
+ prerelease: false
52
+ requirement: &id004 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ type: :runtime
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: rainbow
62
+ prerelease: false
63
+ requirement: &id005 !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: "1"
69
+ type: :runtime
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: rake
73
+ prerelease: false
74
+ requirement: &id006 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ type: :development
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ prerelease: false
85
+ requirement: &id007 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ version: "2"
91
+ type: :development
92
+ version_requirements: *id007
17
93
  description: |
18
94
  A command line tool to enqueue and play music tracks.
19
95
 
@@ -23,19 +99,65 @@ description: |
23
99
 
24
100
  email:
25
101
  - mark@ryall.name
26
- executables: []
27
-
102
+ executables:
103
+ - hearken
28
104
  extensions: []
29
105
 
30
106
  extra_rdoc_files: []
31
107
 
32
108
  files:
33
109
  - .gitignore
110
+ - .rvmrc
34
111
  - Gemfile
112
+ - README.rdoc
35
113
  - Rakefile
114
+ - bin/hearken
36
115
  - hearken.gemspec
37
116
  - lib/hearken.rb
117
+ - lib/hearken/cli.rb
118
+ - lib/hearken/command.rb
119
+ - lib/hearken/command/enqueue.rb
120
+ - lib/hearken/command/flush.rb
121
+ - lib/hearken/command/list.rb
122
+ - lib/hearken/command/recent.rb
123
+ - lib/hearken/command/reload.rb
124
+ - lib/hearken/command/restart.rb
125
+ - lib/hearken/command/scrobbling.rb
126
+ - lib/hearken/command/search.rb
127
+ - lib/hearken/command/setup_scrobbling.rb
128
+ - lib/hearken/command/show_properties.rb
129
+ - lib/hearken/command/shuffle.rb
130
+ - lib/hearken/command/start.rb
131
+ - lib/hearken/command/status.rb
132
+ - lib/hearken/command/stop.rb
133
+ - lib/hearken/console.rb
134
+ - lib/hearken/debug.rb
135
+ - lib/hearken/indexing.rb
136
+ - lib/hearken/indexing/audio_traverser.rb
137
+ - lib/hearken/indexing/executor.rb
138
+ - lib/hearken/indexing/ffmpeg_file.rb
139
+ - lib/hearken/indexing/file.rb
140
+ - lib/hearken/indexing/indexer.rb
141
+ - lib/hearken/indexing/parser.rb
142
+ - lib/hearken/indexing/persistant_traverser.rb
143
+ - lib/hearken/indexing/persisted_traverser.rb
144
+ - lib/hearken/library.rb
145
+ - lib/hearken/player.rb
146
+ - lib/hearken/preferences.rb
147
+ - lib/hearken/queue.rb
148
+ - lib/hearken/range_expander.rb
149
+ - lib/hearken/scrobbler.rb
150
+ - lib/hearken/tagged.rb
151
+ - lib/hearken/track.rb
38
152
  - lib/hearken/version.rb
153
+ - media/applause.mp3
154
+ - spec/hearken/command/enqueue_spec.rb
155
+ - spec/hearken/command/list_spec.rb
156
+ - spec/hearken/command/reload_spec.rb
157
+ - spec/hearken/command/shuffle_spec.rb
158
+ - spec/hearken/player_spec.rb
159
+ - spec/hearken/range_expander_spec.rb
160
+ - spec/spec_helper.rb
39
161
  has_rdoc: true
40
162
  homepage: http://github.com/markryall/hearken
41
163
  licenses: []
@@ -64,5 +186,11 @@ rubygems_version: 1.5.2
64
186
  signing_key:
65
187
  specification_version: 3
66
188
  summary: command line music player
67
- test_files: []
68
-
189
+ test_files:
190
+ - spec/hearken/command/enqueue_spec.rb
191
+ - spec/hearken/command/list_spec.rb
192
+ - spec/hearken/command/reload_spec.rb
193
+ - spec/hearken/command/shuffle_spec.rb
194
+ - spec/hearken/player_spec.rb
195
+ - spec/hearken/range_expander_spec.rb
196
+ - spec/spec_helper.rb