jimmy_jukebox 0.6.0 → 0.6.1

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/bin/play_jukebox CHANGED
@@ -1,33 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $running_jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby') || RUBY_PLATFORM == 'java'
4
-
5
- if $running_jruby
6
- begin
7
- require 'spoon'
8
- rescue LoadError => e
9
- if e.message =~ /spoon/
10
- puts "*** You must run 'gem install spoon' before using JimmyJukebox on JRuby ***"
11
- exit
12
- else
13
- raise
14
- end
15
- end
16
- else
17
- begin
18
- require 'posix/spawn'
19
- rescue LoadError => e
20
- if e.message =~ /posix/ || e.message =~ /spawn/
21
- puts "*** You must run 'gem install posix-spawn' before using JimmyJukebox in Ruby ***"
22
- exit
23
- else
24
- raise
25
- end
26
- end
27
- end
28
-
29
3
  lib = File.expand_path('../lib', File.dirname(__FILE__))
30
4
  $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
+ require 'jimmy_jukebox/check_gems'
31
6
  require 'jimmy_jukebox'
32
7
  include JimmyJukebox
33
8
 
@@ -85,4 +85,9 @@ module Artists
85
85
  name.to_s.split("_").map! { |name_component| name_component.capitalize }.join("") + '.yml'
86
86
  end
87
87
 
88
+ def prettified_artist_name(name)
89
+ return name.to_s.capitalize unless name.to_s.match(/_/)
90
+ name.to_s.split("_").map! { |name_component| name_component.capitalize }.join(" ")
91
+ end
92
+
88
93
  end
@@ -0,0 +1,25 @@
1
+ $running_jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby') || RUBY_PLATFORM == 'java'
2
+
3
+ if $running_jruby
4
+ begin
5
+ require 'spoon'
6
+ rescue LoadError => e
7
+ if e.message =~ /spoon/
8
+ puts "*** You must run 'gem install spoon' before using JimmyJukebox on JRuby ***"
9
+ exit
10
+ else
11
+ raise
12
+ end
13
+ end
14
+ else
15
+ begin
16
+ require 'posix/spawn'
17
+ rescue LoadError => e
18
+ if e.message =~ /posix/ || e.message =~ /spawn/
19
+ puts "*** You must run 'gem install posix-spawn' before using JimmyJukebox in Ruby ***"
20
+ exit
21
+ else
22
+ raise
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,6 @@
1
+ begin
2
+ require 'io/console'
3
+ rescue LoadError
4
+ puts "*** JimmyJukebox uses io/console, which is built into Ruby 1.9.3. I recommend running JimmyJukebox on 1.9.3. You could instead install the 'io-console' gem, but the most recent version works only with 1.9.3, so try \"gem install io-console -v '0.3'\" ***"
5
+ exit
6
+ end
@@ -0,0 +1,9 @@
1
+ if JimmyJukebox::RUNNING_JRUBY
2
+ class IO
3
+ def getch
4
+ raw do
5
+ getc
6
+ end
7
+ end
8
+ end
9
+ end
@@ -8,7 +8,7 @@ module JimmyJukebox
8
8
 
9
9
  def display_options_after_delay
10
10
  # pause to let song display song info and begin playing before displaying user options
11
- sleep 1
11
+ sleep 0.4
12
12
  display_options
13
13
  end
14
14
 
@@ -1,19 +1,49 @@
1
+ require 'jimmy_jukebox/artists'
2
+
1
3
  module JimmyJukebox
2
4
 
3
5
  module HandleLoadJukeboxInput
4
6
 
5
7
  def no_argv0
6
- puts "You must select an artist to use 'load_jukebox'."
7
- puts "For example: 'load_jukebox at' to load Art Tatum"
8
- puts "Another example: 'load_jukebox dr' to load Django Reinhardt"
8
+ display_template {
9
+ puts " You must select an artist or genre to use 'load_jukebox'.\n\n"
10
+ puts " Examples:\n\n"
11
+ puts " load_jukebox at (to download Art Tatum)\n\n"
12
+ puts " load_jukebox dr (to download Django Reinhardt)\n\n"
13
+ puts " load_jukebox bluegrass (to download bluegrass)\n\n"
14
+ puts " load_jukebox classical (to download classical)\n\n"
15
+ puts " load_jukebox jazz (to download jazz)\n\n"
16
+ }
9
17
  exit
10
18
  end
11
19
 
20
+ def list_artists
21
+ display_template {
22
+ puts " Artist symbol = Artist name (Genre)\n\n"
23
+ ARTISTS.each do |k,v|
24
+ puts " " + k.to_s.rjust(5) + ' = ' + prettified_artist_name(v[:name]) + ' (' + v[:genre].capitalize + ')'
25
+ end
26
+ puts "\n"
27
+ }
28
+ end
29
+
12
30
  def invalid_artist
13
- puts "No action taken in response to your command 'load_jukebox #{ARGV[0]}'."
14
- puts "JimmyJukebox does not recognize '#{ARGV[0]}'. You must select a valid artist."
15
- puts "For example, valid artists include: 'bh' for Billie Holiday, 'cb' for Count Basie, and 'lh' for Lionel Hampton"
16
- puts "Please see the README for a complete list of valid artists."
31
+ display_template {
32
+ puts " No action taken in response to your command 'load_jukebox #{ARGV[0]}'.\n\n"
33
+ puts " JimmyJukebox does not recognize '#{ARGV[0]}'.\n\n"
34
+ puts " You must select a valid artist or genre.\n\n"
35
+ puts " Valid genres:\n\n"
36
+ puts " 'bluegrass'"
37
+ puts " 'banjo'"
38
+ puts " 'classical'"
39
+ puts " 'jazz'"
40
+ puts " 'rock'\n\n"
41
+ puts " Valid artists include:\n\n"
42
+ puts " 'bh' for Billie Holiday"
43
+ puts " 'cb' for Count Basie"
44
+ puts " 'lh' for Lionel Hampton.\n\n"
45
+ puts " Please visit the link below for a complete list of valid artists.\n\n"
46
+ }
17
47
  exit
18
48
  end
19
49
 
@@ -35,6 +65,11 @@ module JimmyJukebox
35
65
  arg && arg.to_i.is_a?(Integer) && arg.to_i > 0
36
66
  end
37
67
 
68
+ def play_radio
69
+ require 'jimmy_jukebox/check_gems'
70
+ require 'jimmy_jukebox/user_interface'
71
+ end
72
+
38
73
  def process_artist
39
74
  if valid_integer?(ARGV[1])
40
75
  JimmyJukebox::SongLoader.new.send(artist_name(ARGV[0]), ARGV[1].to_i)
@@ -43,6 +78,31 @@ module JimmyJukebox
43
78
  end
44
79
  end
45
80
 
81
+ def process_genre
82
+ if valid_integer?(ARGV[1])
83
+ JimmyJukebox::SongLoader.new.download_sample_genre(ARGV[1].to_i, ARGV[0].upcase)
84
+ else
85
+ display_genre_download_requires_n_message
86
+ end
87
+ end
88
+
89
+ def display_template(&msg)
90
+ puts " ------------------------------------------------------------------------"
91
+ puts " JimmyJukebox usage help\n\n"
92
+ msg.call if msg
93
+ puts " Full instructions: https://github.com/JamesLavin/jimmy_jukebox"
94
+ puts " ------------------------------------------------------------------------"
95
+ end
96
+
97
+ def display_genre_download_requires_n_message
98
+ display_template {
99
+ puts " You requested a sample of #{ARGV[0]} songs without specifying how many.\n\n"
100
+ puts " Please try again but specify how many songs you wish to download.\n\n"
101
+ puts " For example, to download 10 #{ARGV[0]} songs, type:\n\n"
102
+ puts " load_jukebox #{ARGV[0]} 10"
103
+ }
104
+ end
105
+
46
106
  def process_sample
47
107
  if ARGV[1].nil?
48
108
  JimmyJukebox::SongLoader.new.download_sample_genre(1)
@@ -36,7 +36,7 @@ module JimmyJukebox
36
36
  disable_monitor_powerdown if JimmyJukebox::RUNNING_X_WINDOWS
37
37
  self.user_config = new_user_config
38
38
  self.continuous_play = continuous_play
39
- raise NoSongsException if songs.empty?
39
+ raise NoSongsException if downloaded_song_paths.empty?
40
40
  end
41
41
 
42
42
  def play_loop
@@ -49,10 +49,13 @@ module JimmyJukebox
49
49
  end
50
50
  end
51
51
 
52
+ def next_song?
53
+ @next_song
54
+ end
55
+
52
56
  def next_song
53
57
  # reset @next_song each time it's accessed
54
- current_next_song = @next_song ? @next_song : random_song
55
- @next_song = random_song
58
+ current_next_song, @next_song = [@next_song || random_song, random_song]
56
59
  current_next_song
57
60
  end
58
61
 
@@ -62,7 +65,7 @@ module JimmyJukebox
62
65
 
63
66
  def quit
64
67
  disable_continuous_play
65
- terminate_current_song
68
+ terminate_current_song if current_song
66
69
  end
67
70
 
68
71
  def playing?
@@ -126,15 +129,23 @@ module JimmyJukebox
126
129
  current_song.unpause
127
130
  end
128
131
 
129
- def songs
130
- user_config.songs
132
+ def downloaded_song_paths
133
+ user_config.song_paths
131
134
  end
132
135
 
136
+ #def undownloaded_songs
137
+ # user_config.undownloaded_songs
138
+ #end
139
+
133
140
  def random_song
134
- raise NoNewSongException, "JimmyJukebox can't find any songs to play!" if songs.length == 0
135
- Song.new( songs[rand(songs.length)] )
141
+ raise NoNewSongException, "JimmyJukebox can't find any songs to play!" if downloaded_song_paths.length == 0
142
+ Song.new( downloaded_song_paths[rand(downloaded_song_paths.length)] )
136
143
  end
137
144
 
145
+ #def play_random_undownloaded_song
146
+ # play_song(random_undownloaded_song)
147
+ #end
148
+
138
149
  def play_random_song
139
150
  play_song(random_song)
140
151
  end
@@ -12,6 +12,12 @@ no_argv0 unless ARGV[0]
12
12
 
13
13
  if ARGV[0] =~ /sample/i
14
14
  process_sample
15
+ elsif ARGV[0] =~ /artists/i
16
+ list_artists
17
+ elsif ARGV[0] =~ /radio/i
18
+ play_radio
19
+ elsif valid_genre?(ARGV[0])
20
+ process_genre
15
21
  elsif valid_artist?(ARGV[0])
16
22
  process_artist
17
23
  else
@@ -55,10 +55,12 @@ module JimmyJukebox
55
55
 
56
56
  def pause
57
57
  self.paused = true
58
- if grandchild_pid
59
- `kill -s STOP #{grandchild_pid}`
60
- elsif playing_pid
61
- `kill -s STOP #{playing_pid}`
58
+ if playing_pid
59
+ if grandchild_pid
60
+ `kill -s STOP #{grandchild_pid}`
61
+ else
62
+ `kill -s STOP #{playing_pid}`
63
+ end
62
64
  else
63
65
  raise NoPlayingPidException, "*** Can't pause song because can't find playing_pid #{playing_pid} ***"
64
66
  end
@@ -66,21 +68,21 @@ module JimmyJukebox
66
68
 
67
69
  def unpause
68
70
  self.paused = false
69
- if grandchild_pid
70
- `kill -s CONT #{grandchild_pid}`
71
- elsif playing_pid
71
+ if playing_pid
72
+ if grandchild_pid
73
+ `kill -s CONT #{grandchild_pid}`
74
+ else playing_pid
72
75
  `kill -s CONT #{playing_pid}`
76
+ end
73
77
  else
74
78
  raise NoPlayingPidException, "*** Can't unpause song because can't find playing_pid #{playing_pid} ***"
75
79
  end
76
80
  end
77
81
 
78
82
  def kill_playing_pid_and_children
83
+ return nil unless playpid = playing_pid
79
84
  grandpid = grandchild_pid
80
- playpid = playing_pid
81
- if grandpid
82
- `kill #{grandpid}`
83
- end
85
+ `kill #{grandpid}` if grandpid
84
86
  `kill #{playpid}`
85
87
  end
86
88
 
@@ -41,8 +41,8 @@ module JimmyJukebox
41
41
 
42
42
  attr_reader :user_config
43
43
 
44
- def initialize
45
- @user_config = UserConfig.new
44
+ def initialize(user_config = nil)
45
+ @user_config = user_config || UserConfig.new
46
46
  ARTISTS.values.each { |artist| define_artist artist[:name].to_sym }
47
47
  end
48
48
 
@@ -56,24 +56,24 @@ module JimmyJukebox
56
56
  end
57
57
  end
58
58
 
59
- def all_songs(genre = nil) # valid genres: 'JAZZ', 'CLASSICAL', 'BLUEGRASS', 'BANJO', 'ROCK'
60
- all_songs = {}
59
+ def all_downloadable_songs(genre = nil) # valid genres: 'JAZZ', 'CLASSICAL', 'BLUEGRASS', 'BANJO', 'ROCK'
60
+ result = {}
61
61
  ARTISTS.values.each do |artist|
62
62
  next if genre && artist[:genre] != genre
63
63
  fn = File.dirname(__FILE__) + "/songs/#{artist_name_to_yaml_file(artist[:name].to_s)}"
64
64
  if File.exists?(fn)
65
65
  YAML::load_file(fn).each do |song|
66
- all_songs[song] = artist
66
+ result[song] = artist
67
67
  end
68
68
  end
69
69
  end
70
- all_songs
70
+ result
71
71
  end
72
72
 
73
73
  def sample_genre(num_songs, genre = nil)
74
74
  # loop through array and download num_songs new songs (or until end of array reached)
75
75
  sample = {}
76
- available_songs = all_songs(genre)
76
+ available_songs = all_downloadable_songs(genre)
77
77
  num_songs.times do
78
78
  unless available_songs.length == 0
79
79
  k, v = available_songs.rand_pair!
@@ -2,8 +2,10 @@ require 'fileutils'
2
2
  require 'forwardable'
3
3
  require 'rbconfig'
4
4
 
5
+ require 'jimmy_jukebox/constants'
5
6
  require 'jimmy_jukebox/artists'
6
7
  require 'jimmy_jukebox/song'
8
+ require 'jimmy_jukebox/song_loader'
7
9
  require 'jimmy_jukebox/music_player_detector'
8
10
  include Artists
9
11
 
@@ -29,7 +31,7 @@ module JimmyJukebox
29
31
  extend Forwardable
30
32
 
31
33
  attr_writer :music_directories
32
- attr_accessor :songs, :music_player_detector, :argv0
34
+ attr_accessor :song_paths, :music_player_detector, :argv0
33
35
  def_delegators :@music_player_detector, :ogg_player, :mp3_player, :wav_player, :flac_player
34
36
 
35
37
  DEFAULT_PLAYLIST_DIR = File.expand_path(File.join("~",".jimmy_jukebox"))
@@ -42,7 +44,7 @@ module JimmyJukebox
42
44
  end
43
45
 
44
46
  def initialize
45
- self.songs = []
47
+ self.song_paths = []
46
48
  self.argv0 = ARGV[0]
47
49
  set_music_players
48
50
  generate_directories_list
@@ -195,11 +197,21 @@ module JimmyJukebox
195
197
  end
196
198
  files.delete_if { |f| AUDIO_FORMATS.keys.all? { |re| !f.match(re) } }
197
199
  files.map! { |f| File.expand_path(music_dir) + '/' + f }
198
- files.each { |f| songs << f }
200
+ files.each { |f| song_paths << f }
199
201
  end
200
- puts "WARNING: JimmyJukebox could not find any songs" unless songs.length > 0
201
- #songs = ["~/Music/Artie_Shaw/Georgia On My Mind 1941.mp3",
202
- # "~/Music/Jelly_Roll_Morton/High Society 1939.mp3"]
202
+ puts "WARNING: JimmyJukebox could not find any songs" unless song_paths.length > 0
203
+ #song_paths = ["/home/xxx/Music/Artie_Shaw/Georgia On My Mind 1941.mp3",
204
+ # "/home/xxx/Music/Jelly_Roll_Morton/High Society 1939.mp3"]
205
+ end
206
+
207
+ def undownloaded_songs
208
+ result = {}
209
+ JimmyJukebox::SongLoader.new(self).all_downloadable_songs.each do |url, artist|
210
+ save_path = root_music_dir + artist_name_to_subdir_name(artist[:name]) + '/' + File.basename(url)
211
+ next if song_paths.include?(save_path)
212
+ result[url] = artist
213
+ end
214
+ result
203
215
  end
204
216
 
205
217
  end
@@ -0,0 +1,68 @@
1
+ require 'jimmy_jukebox/check_io_console'
2
+ require 'jimmy_jukebox/jukebox'
3
+ require 'jimmy_jukebox/check_jruby'
4
+
5
+ module JimmyJukebox
6
+
7
+ class UserInputHandler
8
+
9
+ class NoPlayLoopThreadException < Exception; end
10
+
11
+ attr_accessor :jukebox
12
+
13
+ def initialize(jukebox)
14
+ self.jukebox = jukebox
15
+ end
16
+
17
+ def set_get_char_method
18
+ @get_char_method = if JimmyJukebox::RUNNING_JRUBY
19
+ lambda { STDIN.getch }
20
+ else
21
+ lambda {
22
+ begin
23
+ stty_state = `stty -g`
24
+ system("stty raw opost -echo -icanon isig")
25
+ STDIN.getc.chr
26
+ ensure
27
+ `stty #{stty_state}`
28
+ end
29
+ }
30
+ end
31
+ end
32
+
33
+ def get_char
34
+ @get_char_method.call
35
+ end
36
+
37
+ def repl
38
+ set_get_char_method
39
+ loop do
40
+ case char = get_char
41
+ when "q", "Q"
42
+ raise Interrupt
43
+ when "e", "E"
44
+ jukebox.erase_song
45
+ when "p", "P"
46
+ if jukebox.current_song.paused?
47
+ jukebox.unpause_current_song
48
+ else
49
+ puts "Pausing. To unpause, enter 'p' again"
50
+ jukebox.pause_current_song
51
+ end
52
+ when "r", "R"
53
+ jukebox.replay_previous_song
54
+ when "s", "S"
55
+ jukebox.skip_song
56
+ else
57
+ puts "#{char.strip} is not a valid response" if char
58
+ end
59
+ end
60
+ rescue Interrupt, SystemExit => e
61
+ puts "JimmyJukebox closed by user request. Bye!"
62
+ jukebox.quit
63
+ exit
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -1,19 +1,4 @@
1
- begin
2
- require 'io/console'
3
- rescue LoadError
4
- puts "*** JimmyJukebox uses io/console, which is built into Ruby 1.9.3. I recommend running JimmyJukebox on 1.9.3. You could instead install the 'io-console' gem, but the most recent version works only with 1.9.3, so try \"gem install io-console -v '0.3'\" ***"
5
- exit
6
- end
7
-
8
- if JimmyJukebox::RUNNING_JRUBY
9
- class IO
10
- def getch
11
- raw do
12
- getc
13
- end
14
- end
15
- end
16
- end
1
+ require 'jimmy_jukebox/user_input_handler'
17
2
 
18
3
  jj = Jukebox.new
19
4
 
@@ -22,49 +7,13 @@ play_loop_thread = Thread.new do
22
7
  jj.play_loop
23
8
  end
24
9
 
10
+ uih = UserInputHandler.new(jj)
11
+
25
12
  user_input_thread = Thread.new do
26
13
 
27
- class NoPlayLoopThreadException < Exception; end
14
+ raise NoPlayLoopThreadException, "Can't find play_loop_thread" unless play_loop_thread
15
+ uih.repl
28
16
 
29
- begin
30
- loop do
31
- if JimmyJukebox::RUNNING_JRUBY
32
- char = STDIN.getch
33
- else
34
- begin
35
- stty_state = `stty -g`
36
- system("stty raw opost -echo -icanon isig")
37
- char = STDIN.getc.chr
38
- ensure
39
- `stty #{stty_state}`
40
- end
41
- end
42
- case char
43
- when "q", "Q"
44
- raise Interrupt
45
- when "e", "E"
46
- jj.erase_song
47
- when "p", "P"
48
- raise NoPlayLoopThreadException, "Can't find play_loop_thread" unless play_loop_thread
49
- if jj.current_song.paused?
50
- jj.unpause_current_song
51
- else
52
- puts "Pausing. To unpause, enter 'p' again"
53
- jj.pause_current_song
54
- end
55
- when "r", "R"
56
- jj.replay_previous_song
57
- when "s", "S"
58
- jj.skip_song
59
- else
60
- puts "#{char.strip} is not a valid response" if char
61
- end
62
- end
63
- rescue Interrupt, SystemExit => e
64
- puts "JimmyJukebox closed by user request. Bye!"
65
- jj.quit
66
- exit
67
- end
68
17
  end
69
18
 
70
19
  play_loop_thread.join
@@ -1,4 +1,4 @@
1
1
  module JimmyJukebox
2
- VERSION = '0.6.0'
3
- DATE = '2013-03-26'
2
+ VERSION = '0.6.1'
3
+ DATE = '2013-03-28'
4
4
  end
@@ -48,6 +48,7 @@ describe Jukebox do
48
48
  let(:song2_path) { File.expand_path('~/Music/Rock/Beatles/Sgt_Pepper.mp3') }
49
49
  let(:song3_path) { File.expand_path('~/Music/Rock/Eagles/Hotel_California.ogg') }
50
50
  let(:jb) { Jukebox.new(uc) }
51
+ let(:downloaded) { jb.downloaded_song_paths }
51
52
 
52
53
  before do
53
54
  [song1_path, song2_path, song3_path].each do |song|
@@ -59,10 +60,10 @@ describe Jukebox do
59
60
  end
60
61
 
61
62
  it "generates a non-empty song list" do
62
- jb.songs.should_not be_nil
63
- jb.songs.should_not be_empty
64
- jb.songs.length.should == 3
65
- jb.songs.grep(/Abbey_Road.mp3/).length.should == 1
63
+ downloaded.should_not be_nil
64
+ downloaded.should_not be_empty
65
+ downloaded.length.should == 3
66
+ downloaded.grep(/Abbey_Road.mp3/).length.should == 1
66
67
  end
67
68
 
68
69
  it "can quit" do
@@ -72,9 +73,8 @@ describe Jukebox do
72
73
  play_loop_thread = Thread.new do
73
74
  jb.play_loop
74
75
  end
75
- sleep 0.5
76
+ sleep 0.1
76
77
  jb.playing?.should be_true
77
- p jb.current_song
78
78
  jb.quit
79
79
  end
80
80
 
@@ -84,26 +84,26 @@ describe SongLoader do
84
84
 
85
85
  end
86
86
 
87
- describe "#all_songs" do
87
+ describe "#all_downloadable_songs" do
88
88
 
89
89
  context "no genre specified" do
90
90
 
91
- let(:all_songs) { SongLoader.new.all_songs }
91
+ let(:all_downloadable_songs) { SongLoader.new.all_downloadable_songs }
92
92
 
93
93
  it "should include songs from artist lists" do
94
- all_songs.keys.should include "http://archive.org/download/MozartSinfoniaConcertanteK.364spivakovMintz/02Mozart_SinfoniaConcertanteInEFlatK364-2.Andante.mp3"
95
- all_songs.keys.should include "http://archive.org/download/WinnerRagtimeBand-TheTurkeyTrot1912/WinnerRagtimeBand-TurkeyTrot1912.mp3"
94
+ all_downloadable_songs.keys.should include "http://archive.org/download/MozartSinfoniaConcertanteK.364spivakovMintz/02Mozart_SinfoniaConcertanteInEFlatK364-2.Andante.mp3"
95
+ all_downloadable_songs.keys.should include "http://archive.org/download/WinnerRagtimeBand-TheTurkeyTrot1912/WinnerRagtimeBand-TurkeyTrot1912.mp3"
96
96
  end
97
97
 
98
98
  end
99
99
 
100
100
  context "genre 'JAZZ' specified" do
101
101
 
102
- let(:all_songs) { SongLoader.new.all_songs('JAZZ') }
102
+ let(:all_downloadable_songs) { SongLoader.new.all_downloadable_songs('JAZZ') }
103
103
 
104
104
  it "should include only songs from jazz artist lists" do
105
- all_songs.keys.should_not include "http://archive.org/download/MozartSinfoniaConcertanteK.364spivakovMintz/02Mozart_SinfoniaConcertanteInEFlatK364-2.Andante.mp3"
106
- all_songs.keys.should include "http://archive.org/download/WinnerRagtimeBand-TheTurkeyTrot1912/WinnerRagtimeBand-TurkeyTrot1912.mp3"
105
+ all_downloadable_songs.keys.should_not include "http://archive.org/download/MozartSinfoniaConcertanteK.364spivakovMintz/02Mozart_SinfoniaConcertanteInEFlatK364-2.Andante.mp3"
106
+ all_downloadable_songs.keys.should include "http://archive.org/download/WinnerRagtimeBand-TheTurkeyTrot1912/WinnerRagtimeBand-TurkeyTrot1912.mp3"
107
107
  end
108
108
 
109
109
  end
data/spec/song_spec.rb CHANGED
@@ -11,10 +11,12 @@ module JimmyJukebox
11
11
  def spawn_method
12
12
  if JimmyJukebox::RUNNING_JRUBY
13
13
  require 'spoon'
14
- lambda { |command, arg| Spoon.spawnp('sleep 2') }
14
+ lambda { |command, arg| Spoon.spawnp('sleep 5') }
15
15
  else
16
16
  require 'posix/spawn'
17
- lambda { |command, arg| POSIX::Spawn::spawn('sleep 2') }
17
+ # no idea why ';boguscommand' works, but tests fail without it
18
+ #lambda { |command, arg| POSIX::Spawn::spawn('sleep 2; boguscommand') }
19
+ lambda { |command, arg| POSIX::Spawn::spawn('sleep 5') }
18
20
  end
19
21
  end
20
22
  end
@@ -28,16 +30,28 @@ describe Song do
28
30
  expect {Song.new}.to raise_error
29
31
  end
30
32
 
31
- it "fails if parameter does not end in .mp3 or .ogg" do
32
- expect {Song.new("/home/bill/music_file")}.to raise_error
33
+ it "fails if parameter does not have file extension" do
34
+ expect {Song.new(File.expand_path("~/music_file"))}.to raise_error
33
35
  end
34
36
 
35
37
  it "accepts a parameter ending in .mp3" do
36
- Song.new("/home/bill/music_file.mp3").is_a?(Song)
38
+ Song.new(File.expand_path("~/music_file.mp3")).is_a?(Song)
37
39
  end
38
40
 
39
41
  it "accepts a parameter ending in .ogg" do
40
- Song.new("/home/bill/music_file.ogg").is_a?(Song)
42
+ Song.new(File.expand_path("~/music_file.ogg")).is_a?(Song)
43
+ end
44
+
45
+ it "accepts a parameter ending in .flac" do
46
+ Song.new(File.expand_path("~/music_file.flac")).is_a?(Song)
47
+ end
48
+
49
+ it "accepts a parameter ending in .wav" do
50
+ Song.new(File.expand_path("~/music_file.wav")).is_a?(Song)
51
+ end
52
+
53
+ it "handles uppercase file extensions" do
54
+ Song.new(File.expand_path("~/music_file.WAV")).is_a?(Song)
41
55
  end
42
56
 
43
57
  it "sets a music file" do
@@ -46,6 +60,12 @@ describe Song do
46
60
  song.music_file.should == mf
47
61
  end
48
62
 
63
+ it "sets a music file when passed with ~" do
64
+ mf = "~/Music/JAZZ/billie_holiday.ogg"
65
+ song = Song.new(mf)
66
+ song.music_file.should == File.expand_path(mf)
67
+ end
68
+
49
69
  end
50
70
 
51
71
  describe "#paused?" do
@@ -53,26 +73,41 @@ describe Song do
53
73
  before(:each) do
54
74
  @uc = UserConfig.new
55
75
  @jj = Jukebox.new(@uc, false)
56
- @song = Song.new("~/Music/JAZZ/art_tatum.mp3")
57
76
  end
58
77
 
59
78
  it "is initially not paused" do
60
- @jj.play_song(@song)
61
- @song.paused?.should be_false
79
+ Thread.new do
80
+ song = Song.new("~/Music/JAZZ/art_tatum.mp3")
81
+ @jj.play_song(song)
82
+ end
83
+ sleep 0.1
84
+ @jj.should be_playing
85
+ @jj.current_song.paused?.should be_false
86
+ @jj.quit
62
87
  end
63
88
 
64
89
  it "is paused after calling #pause" do
65
- @jj.play_song(@song)
90
+ Thread.new do
91
+ song = Song.new("~/Music/JAZZ/art_tatum.mp3")
92
+ @jj.play_song(song)
93
+ end
94
+ sleep 0.1
66
95
  @jj.pause_current_song
67
- @song.paused?.should be_true
96
+ @jj.current_song.paused?.should be_true
97
+ @jj.quit
68
98
  end
69
99
 
70
100
  it "is unpaused after calling #pause and #unpause" do
71
- @jj.play_song(@song)
72
- @song.pause
73
- @song.paused?.should be_true
74
- @song.unpause
75
- @song.paused?.should be_false
101
+ Thread.new do
102
+ song = Song.new("~/Music/JAZZ/art_tatum.mp3")
103
+ @jj.play_song(song)
104
+ end
105
+ sleep 0.1
106
+ @jj.current_song.pause
107
+ @jj.current_song.paused?.should be_true
108
+ @jj.current_song.unpause
109
+ @jj.current_song.paused?.should be_false
110
+ @jj.quit
76
111
  end
77
112
 
78
113
  end
@@ -82,37 +117,61 @@ describe Song do
82
117
  before(:each) do
83
118
  @uc = UserConfig.new
84
119
  @jj = Jukebox.new(@uc, false)
85
- @song = Song.new("~/Music/JAZZ/art_tatum.mp3")
86
- end
87
-
88
- it "is initially not paused" do
89
- @jj.play_song(@song)
90
- @song.playing_pid.should be_kind_of(Integer)
91
- @jj.skip_song
92
- @song.playing_pid.should be_nil
120
+ @jj.stub(:downloaded_song_paths).and_return(['~/Music/JAZZ/Duke_Ellington/song1.ogg','~/Music/CLASSICAL/Bach/song2.mp3'])
121
+ #@song = Song.new("~/Music/JAZZ/art_tatum.mp3")
93
122
  end
94
123
 
95
124
  end
96
125
 
97
- describe "#play_loop" do
126
+ describe "#play_loop & #skip_song" do
98
127
 
99
128
  before(:each) do
100
129
  @uc = UserConfig.new
101
- #FileUtils.mkdir_p(File.expand_path("~/Music/JAZZ"))
102
- @song = Song.new("~/Music/JAZZ/art_tatum.mp3")
103
- Jukebox.any_instance.stub(:songs).and_return([@song])
104
- Jukebox.any_instance.stub(:next_song).and_return(@song)
105
- end
106
-
107
- it "should automatically play the first song" do
130
+ @song1 = "~/Music/JAZZ/art_tatum.mp3"
131
+ @song2 = "~/Music/JAZZ/dizzy.mp3"
132
+ @song3 = "~/Music/JAZZ/earl_hines.mp3"
133
+ @song4 = "~/Music/CLASSICAL/beethoven.mp3"
108
134
  @jj = Jukebox.new(@uc)
109
- play_loop_thread = Thread.new do
135
+ @jj.stub(:downloaded_song_paths).and_return([@song1, @song2, @song3, @song4])
136
+ @play_loop_thread = Thread.new do
110
137
  @jj.play_loop
111
138
  end
112
139
  sleep 0.1
113
- @jj.playing?.should be_true
114
- play_loop_thread.exit
115
140
  end
141
+
142
+ describe "#play_loop" do
143
+
144
+ it "should automatically play the first song" do
145
+ @jj.should be_playing
146
+ @jj.downloaded_song_paths.map { |f| File.expand_path(f) }.should include @jj.current_song.music_file
147
+ @play_loop_thread.exit
148
+ end
149
+
150
+ end
151
+
152
+ describe "#skip_song" do
153
+
154
+ it "is initially not paused" do
155
+ test_thread = Thread.new do
156
+ @jj.should be_playing
157
+ puts @jj.current_song.playing_pid
158
+ puts @jj.current_song.music_file
159
+ first_song_pid = @jj.current_song.playing_pid
160
+ sleep 0.5
161
+ @jj.skip_song
162
+ puts @jj.current_song.playing_pid
163
+ puts @jj.current_song.music_file
164
+ @jj.current_song.playing_pid.should_not == first_song_pid
165
+ @jj.should be_playing
166
+ end
167
+ [@play_loop_thread, test_thread].each do |t|
168
+ t.join
169
+ end
170
+ @play_loop_thread.exit
171
+ end
172
+
173
+ end
174
+
116
175
  end
117
176
 
118
177
  end
@@ -128,32 +128,60 @@ describe UserConfig do
128
128
 
129
129
  end
130
130
 
131
- describe "#files" do
131
+ describe "#song_paths and #undownloaded_songs" do
132
132
  let(:user_config) { UserConfig.new }
133
- let(:dir1) { '~/Music/artist1' }
134
- let(:dir2) { '~/Music/artist2' }
133
+ let(:dir1) { '~/Music/JAZZ/John_Coltrane' }
134
+ let(:dir2) { '~/Music/CLASSICAL/Vivaldi' }
135
135
  let(:d1) { File.expand_path(dir1) }
136
136
  let(:d2) { File.expand_path(dir2) }
137
137
 
138
138
  before(:each) do
139
139
  FileUtils.mkdir_p(d1)
140
- FileUtils.mkdir_p(d1 + '/subdir')
141
140
  FileUtils.mkdir_p(d2)
142
- FileUtils.touch d1 + '/song1.mp3'
143
- FileUtils.touch d1 + '/subdir/song2.ogg'
144
- FileUtils.touch d1 + '/subdir/song5.afdsdf'
145
- FileUtils.touch d2 + '/song3.flac'
146
- FileUtils.touch d2 + '/song4.wav'
147
- FileUtils.touch d2 + '/song5.WAV'
141
+ FileUtils.touch d1 + '/a_love_supreme.mp3'
142
+ FileUtils.touch d1 + '/my_funny_valentine.ogg'
143
+ FileUtils.touch d1 + '/song5.afdsdf'
144
+ FileUtils.touch d2 + '/four_seasons.flac'
145
+ FileUtils.touch d2 + '/spring.wav'
146
+ FileUtils.touch d2 + '/Summer.WAV'
148
147
  end
149
148
 
150
- it "generates a complete song list" do
151
- user_config.songs.should include File.expand_path(d1 + '/song1.mp3')
152
- user_config.songs.should include File.expand_path(d1 + '/subdir/song2.ogg')
153
- user_config.songs.should include File.expand_path(d2 + '/song3.flac')
154
- user_config.songs.should include File.expand_path(d2 + '/song4.wav')
155
- user_config.songs.should include File.expand_path(d2 + '/song5.WAV')
156
- user_config.songs.length.should == 5
149
+ describe "#song_paths" do
150
+
151
+ it "generates a complete song list" do
152
+ user_config.song_paths.should include File.expand_path(d1 + '/a_love_supreme.mp3')
153
+ user_config.song_paths.should include File.expand_path(d1 + '/my_funny_valentine.ogg')
154
+ user_config.song_paths.should include File.expand_path(d2 + '/four_seasons.flac')
155
+ user_config.song_paths.should include File.expand_path(d2 + '/spring.wav')
156
+ user_config.song_paths.should include File.expand_path(d2 + '/Summer.WAV')
157
+ user_config.song_paths.length.should == 5
158
+ end
159
+
160
+ it "does not include the invalid-formatted song in the list" do
161
+ user_config.song_paths.should_not include File.expand_path(d1 + '/song5.afdsdf')
162
+ end
163
+
164
+ end
165
+
166
+ describe "#undownloaded_songs" do
167
+
168
+ before do
169
+ @song_hash = {'http://www.mp3.com/a_love_supreme.mp3' => {:genre => 'JAZZ', :name => 'john_coltrane'},
170
+ 'http://www.flac.net/four_seasons.flac' => {:genre => 'CLASSICAL', :name => 'vivaldi'},
171
+ 'http://www.wav.com/winter.wav' => {:genre => 'CLASSICAL', :name => 'vivaldi'},
172
+ 'http://www.ogg.org/maybeline.ogg' => {:genre => 'ROCK', :name => 'chuck_berry'}
173
+ }
174
+ end
175
+
176
+ it "correctly generates the list of undownloaded songs" do
177
+ JimmyJukebox::SongLoader.any_instance.stub(:all_downloadable_songs).and_return(@song_hash)
178
+ undownloaded_urls = user_config.undownloaded_songs.keys
179
+ undownloaded_urls.should include 'http://www.wav.com/winter.wav'
180
+ undownloaded_urls.should include 'http://www.ogg.org/maybeline.ogg'
181
+ undownloaded_urls.should_not include 'http://www.flac.net/four_seasons.flac'
182
+ undownloaded_urls.should_not include 'http://www.mp3.com/a_love_supreme.mp3'
183
+ end
184
+
157
185
  end
158
186
 
159
187
  end
@@ -214,39 +242,39 @@ describe UserConfig do
214
242
 
215
243
  let(:uc) { UserConfig.new }
216
244
 
217
- context "with no songs" do
245
+ context "with no song_paths" do
218
246
 
219
- it "finds no songs" do
220
- uc.songs.length.should == 0
247
+ it "finds no song_paths" do
248
+ uc.song_paths.length.should == 0
221
249
  end
222
250
 
223
251
  end
224
252
 
225
- context "with songs in ~/Music" do
253
+ context "with song_paths in ~/Music" do
226
254
 
227
255
  before(:each) do
228
256
  FileUtils.mkdir_p File.expand_path("~/Music")
229
257
  FileUtils.touch File.expand_path("~/Music/Yellow_Submarine.mp3")
230
258
  end
231
259
 
232
- it "finds songs" do
233
- uc.songs.should_not be_empty
234
- uc.songs.length.should == 1
260
+ it "finds song_paths" do
261
+ uc.song_paths.should_not be_empty
262
+ uc.song_paths.length.should == 1
235
263
  end
236
264
 
237
265
  end
238
266
 
239
- context "with songs in ~/Music subdirectory" do
267
+ context "with song_paths in ~/Music subdirectory" do
240
268
 
241
269
  before do
242
270
  FileUtils.mkdir_p File.expand_path("~/Music/ROCK/Beatles")
243
271
  FileUtils.touch File.expand_path("~/Music/ROCK/Beatles/Yellow_Submarine.mp3")
244
272
  end
245
273
 
246
- it "finds songs" do
274
+ it "finds song_paths" do
247
275
  File.directory?(File.expand_path("~/Music/ROCK/Beatles")).should be_true
248
- uc.songs.should_not be_empty
249
- uc.songs.length.should == 1
276
+ uc.song_paths.should_not be_empty
277
+ uc.song_paths.length.should == 1
250
278
  end
251
279
 
252
280
  end
metadata CHANGED
@@ -1,114 +1,125 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jimmy_jukebox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
5
- prerelease:
4
+ prerelease:
5
+ version: 0.6.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - James Lavin
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-26 00:00:00.000000000 Z
12
+ date: 2013-03-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
16
+ version_requirements: !ruby/object:Gem::Requirement
18
17
  requirements:
19
- - - ! '>='
18
+ - - ">="
20
19
  - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :development
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
20
+ version: !binary |-
21
+ MA==
25
22
  none: false
23
+ requirement: !ruby/object:Gem::Requirement
26
24
  requirements:
27
- - - ! '>='
25
+ - - ">="
28
26
  - !ruby/object:Gem::Version
29
- version: '0'
27
+ version: !binary |-
28
+ MA==
29
+ none: false
30
+ prerelease: false
31
+ type: :development
30
32
  - !ruby/object:Gem::Dependency
31
33
  name: rspec-core
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
+ version_requirements: !ruby/object:Gem::Requirement
34
35
  requirements:
35
- - - ! '>='
36
+ - - ">="
36
37
  - !ruby/object:Gem::Version
37
- version: '0'
38
- type: :development
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
38
+ version: !binary |-
39
+ MA==
41
40
  none: false
41
+ requirement: !ruby/object:Gem::Requirement
42
42
  requirements:
43
- - - ! '>='
43
+ - - ">="
44
44
  - !ruby/object:Gem::Version
45
- version: '0'
45
+ version: !binary |-
46
+ MA==
47
+ none: false
48
+ prerelease: false
49
+ type: :development
46
50
  - !ruby/object:Gem::Dependency
47
51
  name: rspec-mocks
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
52
+ version_requirements: !ruby/object:Gem::Requirement
50
53
  requirements:
51
- - - ! '>='
54
+ - - ">="
52
55
  - !ruby/object:Gem::Version
53
- version: '0'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
56
+ version: !binary |-
57
+ MA==
57
58
  none: false
59
+ requirement: !ruby/object:Gem::Requirement
58
60
  requirements:
59
- - - ! '>='
61
+ - - ">="
60
62
  - !ruby/object:Gem::Version
61
- version: '0'
63
+ version: !binary |-
64
+ MA==
65
+ none: false
66
+ prerelease: false
67
+ type: :development
62
68
  - !ruby/object:Gem::Dependency
63
69
  name: rspec-expectations
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
70
+ version_requirements: !ruby/object:Gem::Requirement
66
71
  requirements:
67
- - - ! '>='
72
+ - - ">="
68
73
  - !ruby/object:Gem::Version
69
- version: '0'
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
74
+ version: !binary |-
75
+ MA==
73
76
  none: false
77
+ requirement: !ruby/object:Gem::Requirement
74
78
  requirements:
75
- - - ! '>='
79
+ - - ">="
76
80
  - !ruby/object:Gem::Version
77
- version: '0'
81
+ version: !binary |-
82
+ MA==
83
+ none: false
84
+ prerelease: false
85
+ type: :development
78
86
  - !ruby/object:Gem::Dependency
79
87
  name: fakefs
80
- requirement: !ruby/object:Gem::Requirement
81
- none: false
88
+ version_requirements: !ruby/object:Gem::Requirement
82
89
  requirements:
83
- - - ! '>='
90
+ - - ">="
84
91
  - !ruby/object:Gem::Version
85
- version: '0'
86
- type: :development
87
- prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
92
+ version: !binary |-
93
+ MA==
89
94
  none: false
95
+ requirement: !ruby/object:Gem::Requirement
90
96
  requirements:
91
- - - ! '>='
97
+ - - ">="
92
98
  - !ruby/object:Gem::Version
93
- version: '0'
99
+ version: !binary |-
100
+ MA==
101
+ none: false
102
+ prerelease: false
103
+ type: :development
94
104
  - !ruby/object:Gem::Dependency
95
105
  name: fakeweb
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
106
+ version_requirements: !ruby/object:Gem::Requirement
98
107
  requirements:
99
- - - ! '>='
108
+ - - ">="
100
109
  - !ruby/object:Gem::Version
101
- version: '0'
102
- type: :development
103
- prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
110
+ version: !binary |-
111
+ MA==
105
112
  none: false
113
+ requirement: !ruby/object:Gem::Requirement
106
114
  requirements:
107
- - - ! '>='
115
+ - - ">="
108
116
  - !ruby/object:Gem::Version
109
- version: '0'
110
- description: jimmy_jukebox downloads great music and plays random MP3 & OGG songs
111
- under a directory (or set of directories)
117
+ version: !binary |-
118
+ MA==
119
+ none: false
120
+ prerelease: false
121
+ type: :development
122
+ description: jimmy_jukebox downloads great music and plays random MP3 & OGG songs under a directory (or set of directories)
112
123
  email: james@jameslavin.com
113
124
  executables:
114
125
  - play_jukebox
@@ -119,11 +130,15 @@ files:
119
130
  - roadmap.txt
120
131
  - LICENSE.txt
121
132
  - lib/jimmy_jukebox.rb
133
+ - lib/jimmy_jukebox/check_jruby.rb
122
134
  - lib/jimmy_jukebox/handle_load_jukebox_input.rb
135
+ - lib/jimmy_jukebox/check_gems.rb
136
+ - lib/jimmy_jukebox/user_input_handler.rb
123
137
  - lib/jimmy_jukebox/display_options.rb
124
138
  - lib/jimmy_jukebox/music_player_detector.rb
125
139
  - lib/jimmy_jukebox/load_jukebox_code.rb
126
140
  - lib/jimmy_jukebox/user_interface.rb
141
+ - lib/jimmy_jukebox/check_io_console.rb
127
142
  - lib/jimmy_jukebox/user_config.rb
128
143
  - lib/jimmy_jukebox/jukebox.rb
129
144
  - lib/jimmy_jukebox/constants.rb
@@ -192,27 +207,28 @@ files:
192
207
  - bin/load_jukebox
193
208
  homepage: https://github.com/JamesLavin/jimmy_jukebox
194
209
  licenses: []
195
- post_install_message: I really hope you enjoy the great jazz, classical, bluegrass,
196
- and early rock music downloadable using this gem!
210
+ post_install_message: I really hope you enjoy the great jazz, classical, bluegrass, and early rock music downloadable using this gem!
197
211
  rdoc_options: []
198
212
  require_paths:
199
213
  - lib
200
214
  required_ruby_version: !ruby/object:Gem::Requirement
201
- none: false
202
215
  requirements:
203
- - - ! '>='
216
+ - - ">="
204
217
  - !ruby/object:Gem::Version
205
- version: '0'
206
- required_rubygems_version: !ruby/object:Gem::Requirement
218
+ version: !binary |-
219
+ MA==
207
220
  none: false
221
+ required_rubygems_version: !ruby/object:Gem::Requirement
208
222
  requirements:
209
- - - ! '>='
223
+ - - ">="
210
224
  - !ruby/object:Gem::Version
211
- version: '0'
225
+ version: !binary |-
226
+ MA==
227
+ none: false
212
228
  requirements: []
213
229
  rubyforge_project: jimmy_jukebox
214
- rubygems_version: 1.8.23
215
- signing_key:
230
+ rubygems_version: 1.8.24
231
+ signing_key:
216
232
  specification_version: 3
217
233
  summary: plays your MP3 & OGG files and lets you easily download music
218
234
  test_files:
@@ -224,4 +240,3 @@ test_files:
224
240
  - spec/song_loader_spec.rb
225
241
  - spec/load_jukebox_code_spec.rb
226
242
  - spec/jimmy_jukebox_spec.rb
227
- has_rdoc: