hearken 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|