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.
- data/.gitignore +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +2 -4
- data/README.rdoc +48 -0
- data/Rakefile +5 -0
- data/bin/hearken +7 -0
- data/hearken.gemspec +9 -0
- data/lib/hearken.rb +1 -5
- data/lib/hearken/cli.rb +24 -0
- data/lib/hearken/command.rb +35 -0
- data/lib/hearken/command/enqueue.rb +12 -0
- data/lib/hearken/command/flush.rb +7 -0
- data/lib/hearken/command/list.rb +29 -0
- data/lib/hearken/command/recent.rb +31 -0
- data/lib/hearken/command/reload.rb +7 -0
- data/lib/hearken/command/restart.rb +7 -0
- data/lib/hearken/command/scrobbling.rb +14 -0
- data/lib/hearken/command/search.rb +25 -0
- data/lib/hearken/command/setup_scrobbling.rb +7 -0
- data/lib/hearken/command/show_properties.rb +9 -0
- data/lib/hearken/command/shuffle.rb +13 -0
- data/lib/hearken/command/start.rb +7 -0
- data/lib/hearken/command/status.rb +7 -0
- data/lib/hearken/command/stop.rb +7 -0
- data/lib/hearken/console.rb +34 -0
- data/lib/hearken/debug.rb +16 -0
- data/lib/hearken/indexing.rb +7 -0
- data/lib/hearken/indexing/audio_traverser.rb +19 -0
- data/lib/hearken/indexing/executor.rb +33 -0
- data/lib/hearken/indexing/ffmpeg_file.rb +51 -0
- data/lib/hearken/indexing/file.rb +13 -0
- data/lib/hearken/indexing/indexer.rb +28 -0
- data/lib/hearken/indexing/parser.rb +7 -0
- data/lib/hearken/indexing/persistant_traverser.rb +32 -0
- data/lib/hearken/indexing/persisted_traverser.rb +30 -0
- data/lib/hearken/library.rb +46 -0
- data/lib/hearken/player.rb +91 -0
- data/lib/hearken/preferences.rb +29 -0
- data/lib/hearken/queue.rb +26 -0
- data/lib/hearken/range_expander.rb +30 -0
- data/lib/hearken/scrobbler.rb +76 -0
- data/lib/hearken/tagged.rb +15 -0
- data/lib/hearken/track.rb +38 -0
- data/lib/hearken/version.rb +2 -2
- data/media/applause.mp3 +0 -0
- data/spec/hearken/command/enqueue_spec.rb +24 -0
- data/spec/hearken/command/list_spec.rb +31 -0
- data/spec/hearken/command/reload_spec.rb +20 -0
- data/spec/hearken/command/shuffle_spec.rb +27 -0
- data/spec/hearken/player_spec.rb +37 -0
- data/spec/hearken/range_expander_spec.rb +28 -0
- data/spec/spec_helper.rb +5 -0
- metadata +136 -8
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.2@hearken --create
|
data/Gemfile
CHANGED
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= Hearken
|
2
|
+
|
3
|
+
This is a command line shell for queuing and playing music tracks.
|
4
|
+
|
5
|
+
It also extracts id3 tags from audio files for faster search.
|
6
|
+
|
7
|
+
This will eventually be platform independent but at this stage has only been used on mac os x
|
8
|
+
|
9
|
+
= Usage
|
10
|
+
|
11
|
+
Here you sit expectantly in front of a computer at the command line.
|
12
|
+
|
13
|
+
== Install
|
14
|
+
|
15
|
+
gem install hearken
|
16
|
+
|
17
|
+
== Dependencies
|
18
|
+
|
19
|
+
Tags are currently extracted using ffmpeg. On mac os x, this can be installed easily using brew:
|
20
|
+
|
21
|
+
brew install ffmpeg
|
22
|
+
|
23
|
+
== Indexing tracks
|
24
|
+
|
25
|
+
hearken index DIRECTORY
|
26
|
+
|
27
|
+
Will create a track index at ~/.music. Note that this might take a while the first time you run it.
|
28
|
+
|
29
|
+
Subsequent runs will only query tags for new or modified files so should be fairly fast.
|
30
|
+
|
31
|
+
== Console
|
32
|
+
|
33
|
+
hearken console
|
34
|
+
|
35
|
+
== Commands
|
36
|
+
|
37
|
+
?
|
38
|
+
|
39
|
+
will list all commands
|
40
|
+
|
41
|
+
? <command>
|
42
|
+
|
43
|
+
will describe the use and purpose of a particular command
|
44
|
+
|
45
|
+
= Future plans for world domination
|
46
|
+
|
47
|
+
* Get working on linux
|
48
|
+
* Get working on windows
|
data/Rakefile
CHANGED
data/bin/hearken
ADDED
data/hearken.gemspec
CHANGED
@@ -23,4 +23,13 @@ EOF
|
|
23
23
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
24
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
25
|
s.require_paths = ["lib"]
|
26
|
+
|
27
|
+
s.add_dependency 'thor', '~>0'
|
28
|
+
s.add_dependency 'splat', '~>0'
|
29
|
+
s.add_dependency 'shell_shock', '~>0'
|
30
|
+
s.add_dependency 'simple_scrobbler', '~> 0'
|
31
|
+
s.add_dependency 'rainbow', '~> 1'
|
32
|
+
|
33
|
+
s.add_development_dependency 'rake', '~>0'
|
34
|
+
s.add_development_dependency 'rspec', '~>2'
|
26
35
|
end
|
data/lib/hearken.rb
CHANGED
data/lib/hearken/cli.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
require 'hearken/version'
|
4
|
+
require 'hearken/indexing'
|
5
|
+
require 'hearken/console'
|
6
|
+
|
7
|
+
module Hearken
|
8
|
+
class Cli < Thor
|
9
|
+
desc 'version', 'Prints the current version'
|
10
|
+
def version
|
11
|
+
puts "Current version is "+Hearken::VERSION
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'index DIRECTORY', 'Reindexes a music collection'
|
15
|
+
def index directory
|
16
|
+
Hearken::Indexing::Indexer.new(directory).execute
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'console', 'Enters console for queuing and playing tracks'
|
20
|
+
def console
|
21
|
+
Hearken::Console.new.push
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Hearken
|
2
|
+
module Command
|
3
|
+
attr_reader :usage, :help
|
4
|
+
|
5
|
+
def self.included cls
|
6
|
+
cls.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.load name, *args
|
10
|
+
require "hearken/command/#{name}"
|
11
|
+
classname = name.to_s.split('_').map{|s|s.capitalize}.join
|
12
|
+
Hearken::Command.const_get(classname).new *args
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize player
|
16
|
+
@player = player
|
17
|
+
@usage = ''
|
18
|
+
@help = ''
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def usage usage
|
23
|
+
define_method(:usage) { usage }
|
24
|
+
end
|
25
|
+
|
26
|
+
def help help
|
27
|
+
define_method(:help) { help }
|
28
|
+
end
|
29
|
+
|
30
|
+
def execute &block
|
31
|
+
define_method :execute, block
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'hearken/range_expander'
|
2
|
+
require 'hearken/command'
|
3
|
+
|
4
|
+
class Hearken::Command::Enqueue
|
5
|
+
include Hearken::Command
|
6
|
+
usage '*<id>'
|
7
|
+
help 'enqueues the list of songs with the specified ids'
|
8
|
+
execute do |text|
|
9
|
+
@expander ||= Hearken::RangeExpander.new
|
10
|
+
@expander.expand(text).each {|id| @player.enqueue id }
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'hearken/command'
|
2
|
+
|
3
|
+
class Hearken::Command::List
|
4
|
+
include Hearken::Command
|
5
|
+
usage '*<word>'
|
6
|
+
help <<EOF
|
7
|
+
lists the contents of the track queue
|
8
|
+
these results can optionally be filtered by specified words
|
9
|
+
when playing, approximate times for each track will be displayed
|
10
|
+
EOF
|
11
|
+
execute do |text|
|
12
|
+
@terms = text.split(/\W/)
|
13
|
+
current = @player.current
|
14
|
+
if current
|
15
|
+
next_start_time = Time.at current.started
|
16
|
+
show next_start_time, current
|
17
|
+
end
|
18
|
+
next_start_time += current.time.to_i if next_start_time && current.time
|
19
|
+
@player.each do |track|
|
20
|
+
show next_start_time, track
|
21
|
+
next_start_time += track.time.to_i if next_start_time && track.time
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def show time, track
|
26
|
+
return unless @terms.empty? or @terms.all? {|term| track.search_string.include? term }
|
27
|
+
puts time ? "#{time.to_s.foreground(:blue)}\n\t#{track}" : track
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'hearken/command'
|
2
|
+
|
3
|
+
class Hearken::Command::Recent
|
4
|
+
include Hearken::Command
|
5
|
+
usage '<count>'
|
6
|
+
help 'lists the specified number of recently added albums'
|
7
|
+
execute do |text|
|
8
|
+
@player.library.reload unless @player.library.tracks
|
9
|
+
maximum, current_album, tracks, total_count = text.to_i, nil, [], 0
|
10
|
+
@player.library.tracks.reverse.each do |track|
|
11
|
+
unless current_album
|
12
|
+
current_album = track.album
|
13
|
+
tracks = [track]
|
14
|
+
next
|
15
|
+
end
|
16
|
+
if current_album==track.album
|
17
|
+
tracks << track
|
18
|
+
else
|
19
|
+
puts "#{current_album} - #{extract_artist tracks} - #{tracks.size} tracks (#{tracks.last.search_id}-#{tracks.first.search_id})"
|
20
|
+
current_album = track.album
|
21
|
+
tracks = [track]
|
22
|
+
total_count += 1
|
23
|
+
end
|
24
|
+
break if total_count >= maximum
|
25
|
+
end
|
26
|
+
end
|
27
|
+
private
|
28
|
+
def extract_artist tracks
|
29
|
+
tracks.map{|t| t.artist}.uniq.size == 1 ? tracks.first.artist : 'various artists'
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'hearken/command'
|
2
|
+
|
3
|
+
class Hearken::Command::Scrobbling
|
4
|
+
include Hearken::Command
|
5
|
+
usage '<on|off>'
|
6
|
+
help 'turns interaction with lastfm on or off'
|
7
|
+
execute do |text|
|
8
|
+
scrobbling = (text == 'on')
|
9
|
+
return if @player.scrobbling == scrobbling
|
10
|
+
puts scrobbling ? 'Turning scrobbling on' : 'Turning scrobbling off'
|
11
|
+
@player.scrobbling = scrobbling
|
12
|
+
@player.restart
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'hearken/command'
|
2
|
+
|
3
|
+
class Hearken::Command::Search
|
4
|
+
include Hearken::Command
|
5
|
+
usage '*<word>'
|
6
|
+
help <<EOF
|
7
|
+
searches for tracks containing the specified words (in artist, title or album)
|
8
|
+
ids are placed on the clipboard for convenient use with +
|
9
|
+
EOF
|
10
|
+
execute do |text|
|
11
|
+
terms = text.split(/\W/)
|
12
|
+
matches = []
|
13
|
+
@player.library.reload unless @player.library.tracks
|
14
|
+
matches = []
|
15
|
+
@player.library.tracks.each do |track|
|
16
|
+
if terms.all? {|term| track.search_string.include? term }
|
17
|
+
puts track
|
18
|
+
matches << track.search_id
|
19
|
+
end
|
20
|
+
end
|
21
|
+
puts "Found #{matches.size} matches (ids have been placed on clipboard)"
|
22
|
+
matches.join(' ').to_clipboard
|
23
|
+
@player.matches = matches
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'hearken/command'
|
2
|
+
|
3
|
+
class Hearken::Command::Shuffle
|
4
|
+
include Hearken::Command
|
5
|
+
help 'shuffles the current queue'
|
6
|
+
execute do |ignored=nil|
|
7
|
+
ids = []
|
8
|
+
while id = @player.dequeue
|
9
|
+
ids << id
|
10
|
+
end
|
11
|
+
ids.sort_by { rand }.each {|id| @player.enqueue id }
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'shell_shock/context'
|
2
|
+
|
3
|
+
require 'hearken/player'
|
4
|
+
require 'hearken/preferences'
|
5
|
+
require 'hearken/command'
|
6
|
+
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
module Hearken
|
10
|
+
class Console
|
11
|
+
include ShellShock::Context
|
12
|
+
|
13
|
+
def with name, *aliases
|
14
|
+
aliases << name.to_s if aliases.empty?
|
15
|
+
add_command Command.load(name, @player), *aliases
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_all *names
|
19
|
+
names.each {|name| with name}
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
preferences = Preferences.new
|
24
|
+
@player = Player.new preferences
|
25
|
+
at_exit { @player.stop }
|
26
|
+
@prompt = "hearken > "
|
27
|
+
with :status, "'"
|
28
|
+
with :show_properties, 'show'
|
29
|
+
with :restart, 'next'
|
30
|
+
with :enqueue, '+'
|
31
|
+
with_all *%w{reload search start stop scrobbling shuffle list setup_scrobbling recent flush}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|