hearken 0.0.1 → 0.0.2

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.
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