jimmy_jukebox 0.4.2 → 0.4.3

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.
@@ -1,48 +1,69 @@
1
1
  module Artists
2
2
 
3
- JAZZ_ARTISTS = {
4
- :acb => "archibald_camp_banjo",
5
- :at => "art_tatum",
6
- :as => "artie_shaw",
7
- :bg => "benny_goodman",
8
- :bh => "billie_holiday",
9
- :bb => "bix_beiderbecke",
10
- :bm => "bennie_moten",
11
- :cc => "charlie_christian",
12
- :cp => "charlie_parker",
13
- :ch => "coleman_hawkins",
14
- :chjb => "clifford_hayes_jug_blowers",
15
- :cb => "count_basie",
16
- :dx => "dixieland",
17
- :dg => "dizzy_gillespie",
18
- :dr => "django_reinhardt",
19
- :de => "duke_ellington",
20
- :eh => "earl_hines",
21
- :fh => "fletcher_henderson",
22
- :jj => "james_p_johnson",
23
- :jrm => "jelly_roll_morton",
24
- :ko => "king_oliver",
25
- :la => "louis_armstrong",
26
- :lh => "lionel_hampton",
27
- :md => "miles_davis",
28
- :odjb => "original_dixieland_jazz_band",
29
- :rt => "ragtime",
30
- :rn => "red_norvo",
31
- :sb => "sidney_bechet"
3
+ ARTISTS = {
4
+ acb: { genre: 'BANJO', name: "archibald_camp_banjo" },
5
+ at: { genre: 'JAZZ', name: "art_tatum" },
6
+ as: { genre: 'JAZZ', name: "artie_shaw"},
7
+ bg: { genre: 'JAZZ', name: "benny_goodman"},
8
+ bh: { genre: 'JAZZ', name: "billie_holiday"},
9
+ bb: { genre: 'JAZZ', name: "bix_beiderbecke"},
10
+ bm: { genre: 'JAZZ', name: "bennie_moten"},
11
+ cc: { genre: 'JAZZ', name: "charlie_christian"},
12
+ cp: { genre: 'JAZZ', name: "charlie_parker"},
13
+ ch: { genre: 'JAZZ', name: "coleman_hawkins"},
14
+ chjb: { genre: 'JAZZ', name: "clifford_hayes_jug_blowers"},
15
+ cb: { genre: 'JAZZ', name: "count_basie"},
16
+ dx: { genre: 'JAZZ', name: "dixieland"},
17
+ dg: { genre: 'JAZZ', name: "dizzy_gillespie"},
18
+ dr: { genre: 'JAZZ', name: "django_reinhardt"},
19
+ de: { genre: 'JAZZ', name: "duke_ellington"},
20
+ eh: { genre: 'JAZZ', name: "earl_hines"},
21
+ fh: { genre: 'JAZZ', name: "fletcher_henderson"},
22
+ jj: { genre: 'JAZZ', name: "james_p_johnson"},
23
+ jrm: { genre: 'JAZZ', name: "jelly_roll_morton"},
24
+ ko: { genre: 'JAZZ', name: "king_oliver"},
25
+ la: { genre: 'JAZZ', name: "louis_armstrong"},
26
+ lh: { genre: 'JAZZ', name: "lionel_hampton"},
27
+ lvb: { genre: 'CLASSICAL', name: "beethoven"},
28
+ md: { genre: 'JAZZ', name: "miles_davis"},
29
+ odjb: { genre: 'JAZZ', name: "original_dixieland_jazz_band"},
30
+ rt: { genre: 'JAZZ', name: "ragtime"},
31
+ rn: { genre: 'JAZZ', name: "red_norvo"},
32
+ sb: { genre: 'JAZZ', name: "sidney_bechet"}
32
33
  }
33
34
 
34
- def key_to_subdir_name(key)
35
- value_to_subdir_name(JAZZ_ARTISTS[key.to_sym])
35
+ def artist_genre(key)
36
+ ARTISTS[key][:genre]
36
37
  end
37
38
 
38
- def value_to_subdir_name(value)
39
- return '/JAZZ/' + value.to_s.capitalize unless value.to_s.match(/_/)
40
- '/JAZZ/' + value.to_s.split("_").map! { |name_component| name_component.capitalize }.join("_")
39
+ def artist_name(key)
40
+ ARTISTS[key][:name]
41
41
  end
42
42
 
43
- def value_to_yaml_file(value)
44
- return value.to_s.capitalize + '.yml' unless value.to_s.match(/_/)
45
- value.to_s.split("_").map! { |name_component| name_component.capitalize }.join("") + '.yml'
43
+ def artist_name_to_genre(name)
44
+ p "looking for #{name}"
45
+ artists = ARTISTS.select { |k,v| v[:name] == name }
46
+ p artists
47
+ key, value = artists.first
48
+ value[:genre]
49
+ end
50
+
51
+ def artist_name_to_subdir_name(name)
52
+ return "/#{artist_name_to_genre(name)}/" + name.to_s.capitalize unless name.to_s.match(/_/)
53
+ "/#{artist_name_to_genre(name)}/" + name.to_s.split("_").map! { |name_component| name_component.capitalize }.join("_")
54
+ end
55
+
56
+ def artist_key_to_subdir_name(key)
57
+ artist_name_to_subdir_name(artist_name(key))
58
+ end
59
+
60
+ def artist_key_to_yaml_file(key)
61
+ artist_name_to_yaml_file(artist_name(key))
62
+ end
63
+
64
+ def artist_name_to_yaml_file(name)
65
+ return name.to_s.capitalize + '.yml' unless name.to_s.match(/_/)
66
+ name.to_s.split("_").map! { |name_component| name_component.capitalize }.join("") + '.yml'
46
67
  end
47
68
 
48
69
  end
@@ -4,6 +4,7 @@ module JimmyJukebox
4
4
 
5
5
  class Jukebox
6
6
 
7
+ class NoSongsException < Exception; end
7
8
  class NoNewSongException < Exception; end
8
9
  class NoCurrentSongException < Exception; end
9
10
  class NoPreviousSongException < Exception; end
@@ -14,6 +15,7 @@ module JimmyJukebox
14
15
  def initialize(new_user_config = UserConfig.new, continuous_play = true)
15
16
  self.user_config = new_user_config
16
17
  self.continuous_play = continuous_play
18
+ raise NoSongsException if songs.empty?
17
19
  end
18
20
 
19
21
  def play_loop
@@ -121,7 +123,7 @@ module JimmyJukebox
121
123
  self.songs_played << song
122
124
  current_song.play(user_config, self)
123
125
  p "Finished playing"
124
- p "Songs played: " + songs_played.to_s
126
+ #p "Songs played: " + songs_played.to_s
125
127
  self.current_song = nil
126
128
  self.playing = false
127
129
  rescue Song::SongTerminatedPrematurelyException
@@ -22,6 +22,9 @@ def invalid_artist
22
22
  end
23
23
 
24
24
  no_argv0 unless ARGV[0]
25
- invalid_artist unless JAZZ_ARTISTS.has_key?(ARGV[0].to_sym)
26
- JimmyJukebox::SongLoader.send(JAZZ_ARTISTS[ARGV[0].to_sym])
27
25
 
26
+ if ARTISTS.has_key?(ARGV[0].to_sym)
27
+ JimmyJukebox::SongLoader.send(ARTISTS[ARGV[0].to_sym][:name])
28
+ else
29
+ invalid_artist
30
+ end
@@ -94,6 +94,23 @@ module JimmyJukebox
94
94
  end
95
95
  end
96
96
 
97
+ def spawn_method
98
+ if $running_jruby
99
+ lambda { |command, arg| Spoon.spawnp(command, arg) }
100
+ else
101
+ begin
102
+ lambda { |command, arg| POSIX::Spawn::spawn(command + ' ' + arg) }
103
+
104
+ # posix/spawn is much faster than fork-exec
105
+ #pid = Process.fork do
106
+ # exec(command + ' ' + arg)
107
+ #end
108
+ rescue NotImplementedError
109
+ raise CannotSpawnProcessException, "*** Cannot play music because we found neither Spoon.spawnp (for JRuby) nor Process.fork (for MRI) ***"
110
+ end
111
+ end
112
+ end
113
+
97
114
  def play(user_config, jukebox)
98
115
  set_player(user_config)
99
116
  process_status = play_with_player
@@ -114,21 +131,7 @@ module JimmyJukebox
114
131
 
115
132
  def run_command(command, arg)
116
133
  # make system call and get pid so you can pause/terminate process
117
- if $running_jruby
118
- pid = Spoon.spawnp(command,arg)
119
- else
120
- begin
121
- pid = POSIX::Spawn::spawn(command + ' ' + arg)
122
-
123
- # posix/spawn is much faster than fork-exec
124
- #pid = Process.fork do
125
- # exec(command + ' ' + arg)
126
- # exit! 127 # should never be reached
127
- #end
128
- rescue NotImplementedError
129
- raise CannotSpawnProcessException, "*** Cannot play music because we found neither Spoon.spawnp (for JRuby) nor Process.fork (for MRI) ***"
130
- end
131
- end
134
+ pid = spawn_method.call(command, arg)
132
135
  self.playing_pid = pid
133
136
  end
134
137
 
@@ -27,14 +27,14 @@ module JimmyJukebox
27
27
  def self.define_artist(name,user_config)
28
28
  metaclass.instance_eval do
29
29
  define_method(name) do
30
- save_dir = user_config.default_music_dir + value_to_subdir_name(name)
31
- songs = YAML::load_file(File.dirname(__FILE__) + "/songs/#{value_to_yaml_file(name)}")
30
+ save_dir = user_config.default_music_dir + artist_name_to_subdir_name(name.to_s)
31
+ songs = YAML::load_file(File.dirname(__FILE__) + "/songs/#{artist_name_to_yaml_file(name.to_s)}")
32
32
  download_songs(songs, save_dir)
33
33
  end
34
34
  end
35
35
  end
36
36
 
37
- JAZZ_ARTISTS.values.each { |v| define_artist v.to_sym, @user_config }
37
+ ARTISTS.values.each { |artist| define_artist artist[:name].to_sym, @user_config }
38
38
 
39
39
  def self.sample(num_songs)
40
40
  # create array of all possible songs
@@ -80,14 +80,24 @@ module JimmyJukebox
80
80
  end
81
81
  end
82
82
 
83
- def self.download_song(song_url, save_dir)
84
- song_savename = File.basename(song_url)
85
- if version_of_song_in_any_dir?(song_savename, save_dir)
86
- puts "#{song_savename} already exists in #{save_dir}"
87
- return
83
+ def self.song_savename(song_url)
84
+ File.basename(song_url)
85
+ end
86
+
87
+ def self.song_already_exists?(savename, save_dir)
88
+ if version_of_song_in_any_dir?(savename, save_dir)
89
+ puts "#{savename} already exists in #{save_dir}"
90
+ true
91
+ else
92
+ false
88
93
  end
89
- puts "Downloading #{song_savename}"
90
- song_pathname = File.join(save_dir,song_savename)
94
+ end
95
+
96
+ def self.download_song(song_url, save_dir)
97
+ savename = song_savename(song_url)
98
+ return if song_already_exists?(savename, save_dir)
99
+ puts "Downloading #{savename}"
100
+ song_pathname = File.join(save_dir, savename)
91
101
  open(song_pathname, 'wb') do |dst|
92
102
  open(song_url) do |src|
93
103
  dst.write(src.read)
@@ -97,7 +107,7 @@ module JimmyJukebox
97
107
  rescue OpenURI::HTTPError
98
108
  p "Warning: Could not download #{song_url}"
99
109
  File.delete(song_pathname) if File.exists?(song_pathname)
100
- return nil
110
+ nil
101
111
  end
102
112
 
103
113
  def self.check_downloaded_song_size(song_pathname)
@@ -0,0 +1,51 @@
1
+ ---
2
+ - http://archive.org/download/BeethovenSymphonyNo.1/1.mp3
3
+ - http://archive.org/download/BBCSymphony2Beethoven/symphony2_beethoven_radio3.mp3
4
+ - http://archive.org/download/bbcSymphony3Beethoven_2/symphony3_beethoven_radio3.mp3
5
+ - http://archive.org/download/BeethovenSymphonyNo.3walter/I.AllegroConBrio.mp3
6
+ - http://archive.org/download/BeethovenSymphonyNo.3walter/Ii.MarciaFunebreAdagioAssai.mp3
7
+ - http://archive.org/download/BeethovenSymphonyNo.3walter/Iii.Scherzo-AllegroVivaceTrio.mp3
8
+ - http://archive.org/download/BeethovenSymphonyNo.3walter/Iv.Finale-AllegroMoltoPocoAndante.mp3
9
+ - http://archive.org/download/BeethovenSymphonyNo.4/I.Adagio_AllegroVivace.mp3
10
+ - http://archive.org/download/BeethovenSymphonyNo.4/Ii.Adagio.mp3
11
+ - http://archive.org/download/BeethovenSymphonyNo.4/Iii.Scherzo-AllegroVivace_Trio-UnPocoMenoAllegro.mp3
12
+ - http://archive.org/download/BeethovenSymphonyNo.4/Iv.AllegroMaNonTroppo.mp3
13
+ - http://archive.org/download/Beethovens5th/01SymphonyNo.5InCMinor.mp3
14
+ - http://archive.org/download/BeethovenSymphonyNo.5/ToscaniniBeethoven5.mp3
15
+ - http://archive.org/download/BBCSymphony6Beethoven/symphony6_beethoven_radio3.mp3
16
+ - http://archive.org/download/BeethovenSymphonyNo.7-ormandy/I.PocoSostenutoVivace.mp3
17
+ - http://archive.org/download/BeethovenSymphonyNo.7-ormandy/Ii.Allegretto.mp3
18
+ - http://archive.org/download/BeethovenSymphonyNo.7-ormandy/Iii.Presto.mp3
19
+ - http://archive.org/download/BeethovenSymphonyNo.7-ormandy/Iv.AllegroConMoto.mp3
20
+ - http://archive.org/download/BBCSymphony8Beethoven/symphony8_beethoven_radio3.mp3
21
+ - http://archive.org/download/BeethovenSymphonyNo.8/01.allegroVivaceEConBrio.mp3
22
+ - http://archive.org/download/BeethovenSymphonyNo.8/02.scherzandoAllegretto.mp3
23
+ - http://archive.org/download/BeethovenSymphonyNo.8/03.tempoDiMenuetto.mp3
24
+ - http://archive.org/download/BeethovenSymphonyNo.8/04.allegroVivace.mp3
25
+ - http://archive.org/download/BeethovenViolinConcertoheifetz/I.AllegroMaNonTroppo.mp3
26
+ - http://archive.org/download/BeethovenViolinConcertoheifetz/Ii.Larghetto.mp3
27
+ - http://archive.org/download/BeethovenViolinConcertoheifetz/Iii.Rondoallegro.mp3
28
+ - http://archive.org/download/BeethovenViolinConcerto-Szigeti/01I.AllegroMaNonTroppo.mp3
29
+ - http://archive.org/download/BeethovenViolinConcerto-Szigeti/02Ii.LarghettoIii.Rondo.mp3
30
+ - http://archive.org/download/BeethovenFrElise-Schnabel/Beethoven-FrEliseWoo59.mp3
31
+ - http://archive.org/download/BeethovenRondoInG/Beethoven-RondoInGMajor.mp3
32
+ - http://archive.org/download/BeethovenElevenVienneseDances/Beethoven-ElevenVienneseDancesWoo17.mp3
33
+ - http://archive.org/download/BeethovenCoriolanOverture/Beethoven-CoriolonOverture.mp3
34
+ - http://archive.org/download/MoonlightSonata_755/Beethoven-MoonlightSonata.mp3
35
+ - http://archive.org/download/BeethovenPianoSonataNo.2/BeethovenSonata2.ogg
36
+ - http://archive.org/download/BeethovenPianoSonataNo.3/BeethovenSonata3.ogg
37
+ - http://archive.org/download/BeethovenPianoSonataNo.6/BeethovenSonata6.mp3
38
+ - http://archive.org/download/BeethovenPianoSonata13/BeethovenPianoSonata13.mp3
39
+ - http://archive.org/download/BeethovenPianoSonata15/BeethovenPianoSonata15.mp3
40
+ - http://archive.org/download/BeethovenPianoSonata16/BeethovenPianoSonata16.mp3
41
+ - http://archive.org/download/BeethovenPianoSonata17/BeethovenPianoSonata17.mp3
42
+ - http://archive.org/download/BeethovenPianoSonata22/BeethovenPianoSonata22.mp3
43
+ - http://archive.org/download/BeethovenPianoSonataNo.25/BeethovenPianoSonata25.mp3
44
+ - http://archive.org/download/BeethovenSonata31Opus110/KatieAconeBeethovenSonata31Opus110.mp3
45
+ - http://archive.org/download/BeethovenTripleConcerto/01I.Allegro.mp3
46
+ - http://archive.org/download/BeethovenTripleConcerto/02Ii.LargoIii.RondoAllaPolacca.mp3
47
+ - http://archive.org/download/BeethovenTrioOp.11-Adagio/BeethovenTrio.mp3
48
+ - http://archive.org/download/GlennGould-BeethovenPianoSonatas/01-Beethoven-SonataNo.1InFMinorOp.2No.1-I.Allegro-GlennGould.mp3
49
+ - http://archive.org/download/GlennGould-BeethovenPianoSonatas/05-Beethoven-SonataNo.2InAMajorOp.2No.2-I.AllegroVivace-GlennGould.mp3
50
+ - http://archive.org/download/GlennGould-BeethovenPianoSonatas/09-Beethoven-SonataNo.3InCMajorOp.2No.3-I.AllegroConBrio-GlennGould.mp3
51
+
@@ -1,5 +1,13 @@
1
1
  ---
2
2
  - http://archive.org/download/CharlieChristian-SevenComeEleven/02.SevenComeEleven.mp3
3
+ - http://archive.org/download/Daddy_GS_CHARLIE_CHRISTIAN_Guitar_Hero/ChristianCharlieoriginalGuitarHero-BennysBugle.mp3
4
+ - http://archive.org/download/Daddy_GS_CHARLIE_CHRISTIAN_Guitar_Hero/ChristianCharlieoriginalGuitarHero-BoyMeetsGoygrandSlam.mp3
5
+ - http://archive.org/download/Daddy_GS_CHARLIE_CHRISTIAN_Guitar_Hero/ChristianCharlieoriginalGuitarHero-BreakfastFeudsecondVersion.mp3
6
+ - http://archive.org/download/Daddy_GS_CHARLIE_CHRISTIAN_Guitar_Hero/ChristianCharlieoriginalGuitarHero-FlyingHomealternateTake.mp3
7
+ - http://archive.org/download/Daddy_GS_CHARLIE_CHRISTIAN_Guitar_Hero/ChristianCharlieoriginalGuitarHero-GoneWithwhatWindalternateTake.mp3
8
+ - http://archive.org/download/Daddy_GS_CHARLIE_CHRISTIAN_Guitar_Hero/ChristianCharlieoriginalGuitarHero-GoodEnoughToKeepairMailSpecialfirstVersion--AlternateTak.mp3
9
+ - http://archive.org/download/Daddy_GS_CHARLIE_CHRISTIAN_Guitar_Hero/ChristianCharlieoriginalGuitarHero-SevenComeEleven.mp3
10
+ - http://archive.org/download/Daddy_GS_CHARLIE_CHRISTIAN_Guitar_Hero/ChristianCharlieoriginalGuitarHero-WhollyCats.mp3
3
11
  #- http://www.archive.org/download/CharlieChristian-01-08/CharlieChristian-AirmailSpecial.mp3
4
12
  #- http://www.archive.org/download/CharlieChristian-01-08/CharlieChristian-BluesInB.mp3
5
13
  #- http://www.archive.org/download/CharlieChristian-01-08/CharlieChristian-HoneysuckleRose1939.mp3
@@ -69,8 +69,6 @@ module JimmyJukebox
69
69
  # return
70
70
  #elsif (require 'rbconfig') && ['mac','darwin'].include?(RbConfig::CONFIG['host_os'])
71
71
  # ogg_player = "afplay"
72
- else
73
- raise NoOggPlayerFoundException, "Could not find an Ogg Vorbis player"
74
72
  end
75
73
  end
76
74
 
@@ -96,8 +94,6 @@ module JimmyJukebox
96
94
  # return
97
95
  #elsif (require 'rbconfig') && ['mac','darwin'].include?(RbConfig::CONFIG['host_os'])
98
96
  # mp3_player = "afplay"
99
- else
100
- raise NoMP3PlayerFoundException, "Could not find an MP3 player"
101
97
  end
102
98
  end
103
99
 
@@ -147,8 +143,8 @@ module JimmyJukebox
147
143
  # puts "ARGV: " + ARGV.inspect + " (" + ARGV.class.to_s + ")"
148
144
  if ARGV.empty?
149
145
  music_directories << default_music_dir
150
- elsif JAZZ_ARTISTS.keys.include?(ARGV[0].to_sym)
151
- music_directories << default_music_dir + key_to_subdir_name(ARGV[0].to_sym)
146
+ elsif ARTISTS.keys.include?(ARGV[0].to_sym)
147
+ music_directories << default_music_dir + artist_key_to_subdir_name(ARGV[0].to_sym)
152
148
  elsif is_a_txt_file?(ARGV[0])
153
149
  set_music_directories_from_file
154
150
  elsif is_a_directory?(ARGV[0])
@@ -185,10 +181,16 @@ module JimmyJukebox
185
181
  end
186
182
  end
187
183
 
184
+ def all_subdirectories(dir)
185
+ Dir.glob(File.join(dir,"**/","*/"))
186
+ .delete_if {|dir_name| !File.directory?(dir_name)}
187
+ .map { |dir_name| File.expand_path(dir_name) }
188
+ end
189
+
188
190
  def add_all_subdirectories
189
191
  new_dirs = []
190
192
  music_directories.each do |dir|
191
- new_dirs = new_dirs + Dir.glob(File.join(dir,"**/")).map { |dir_name| File.expand_path(dir_name) }
193
+ new_dirs = new_dirs + all_subdirectories(dir)
192
194
  end
193
195
  self.music_directories = music_directories + new_dirs
194
196
  end
@@ -1,4 +1,4 @@
1
1
  module JimmyJukebox
2
- VERSION = '0.4.2'
3
- DATE = '2013-02-22'
2
+ VERSION = '0.4.3'
3
+ DATE = '2013-02-25'
4
4
  end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/jimmy_jukebox/artists'
3
+ include Artists
4
+
5
+ #describe Jukebox do
6
+
7
+ describe Artists do
8
+
9
+ describe "::ARTISTS" do
10
+ it "has the correct keys" do
11
+ Artists::ARTISTS.keys.should include(:ch)
12
+ end
13
+
14
+ it "has the correct values for each key" do
15
+ Artists::ARTISTS[:eh].should == { genre: 'JAZZ', name: 'earl_hines' }
16
+ end
17
+ end
18
+
19
+ describe "#artist_genre" do
20
+ it "provides the artist's genre" do
21
+ artist_genre(:lvb).should == 'CLASSICAL'
22
+ artist_genre(:jrm).should == 'JAZZ'
23
+ end
24
+ end
25
+
26
+ describe "#artist_name" do
27
+ it "provides the artist's name" do
28
+ artist_name(:lh).should == 'lionel_hampton'
29
+ artist_name(:bg).should == 'benny_goodman'
30
+ end
31
+ end
32
+
33
+ describe "#artist_name_to_genre" do
34
+ it "provides the artist's genre" do
35
+ artist_name_to_genre('sidney_bechet').should == 'JAZZ'
36
+ artist_name_to_genre('beethoven').should == 'CLASSICAL'
37
+ end
38
+ end
39
+
40
+ describe "#artist_name_to_subdir_name" do
41
+ it "provides the artist's subdirectory name" do
42
+ artist_name_to_subdir_name('dixieland').should == '/JAZZ/Dixieland'
43
+ artist_name_to_subdir_name('miles_davis').should == '/JAZZ/Miles_Davis'
44
+ artist_name_to_subdir_name('beethoven').should == '/CLASSICAL/Beethoven'
45
+ end
46
+ end
47
+
48
+ describe "#artist_key_to_subdir_name" do
49
+ it "provides the artist's subdirectory name" do
50
+ artist_key_to_subdir_name(:dx).should == '/JAZZ/Dixieland'
51
+ artist_key_to_subdir_name(:md).should == '/JAZZ/Miles_Davis'
52
+ artist_key_to_subdir_name(:lvb).should == '/CLASSICAL/Beethoven'
53
+ end
54
+ end
55
+
56
+ describe "#artist_key_to_yaml_file" do
57
+ it "provides the artist's subdirectory name" do
58
+ artist_key_to_yaml_file(:dx).should == 'Dixieland.yml'
59
+ artist_key_to_yaml_file(:md).should == 'MilesDavis.yml'
60
+ artist_key_to_yaml_file(:lvb).should == 'Beethoven.yml'
61
+ end
62
+ end
63
+
64
+ describe "#artist_name_to_yaml_file" do
65
+ it "provides the artist's subdirectory name" do
66
+ artist_name_to_yaml_file('dixieland').should == 'Dixieland.yml'
67
+ artist_name_to_yaml_file('miles_davis').should == 'MilesDavis.yml'
68
+ artist_name_to_yaml_file('beethoven').should == 'Beethoven.yml'
69
+ end
70
+ end
71
+ end
@@ -2,6 +2,15 @@ require 'spec_helper'
2
2
  require_relative '../lib/jimmy_jukebox/jukebox'
3
3
  include JimmyJukebox
4
4
 
5
+ # don't actually play music
6
+ module JimmyJukebox
7
+ class Song
8
+ def spawn_method(command, arg)
9
+ lambda { |command, arg| sleep(5) }
10
+ end
11
+ end
12
+ end
13
+
5
14
  describe Jukebox do
6
15
 
7
16
  include FakeFS::SpecHelpers
@@ -13,54 +22,51 @@ describe Jukebox do
13
22
  let(:jb) { Jukebox.new }
14
23
 
15
24
  let(:uc) { double('user_config').as_null_object }
16
-
17
25
 
18
26
  context "with no command line parameter" do
19
27
 
20
- it "exists" do
21
- jb.should_not be_nil
22
- jb.quit
23
- end
24
-
25
- it "calls play_random_song" do
26
- jb.stub(:play_random_song).and_return(nil)
27
- jb.should_receive(:play_once)
28
- jb.play_once
29
- jb.quit
30
- end
31
-
32
- it "raises exception when no songs available" do
33
- expect { jb.play_once }.to raise_error(Jukebox::NoSongException)
34
- end
35
-
36
- it "has a user_config method" do
37
- jb.user_config.is_a?(UserConfig)
38
- end
39
-
40
- it "generates an empty song list" do
41
- jb.user_config.songs.should be_empty
42
- jb.user_config.songs.length.should == 0
28
+ context "when no songs available" do
29
+ it "raises exception when no songs available" do
30
+ expect { jb }.to raise_error(Jukebox::NoSongsException)
31
+ end
43
32
  end
44
33
 
45
34
  context "when songs exist" do
46
35
 
47
- let(:song1) { '/home/xavier/Music/Rock/Beatles/Abbey_Road.mp3' }
48
- let(:song2) { '/home/xavier/Music/Rock/Beatles/Sgt_Pepper.mp3' }
49
- let(:song3) { '/home/xavier/Music/Rock/Eagles/Hotel_California.ogg' }
36
+ let(:song1) { File.expand_path('~/Music/Rock/Beatles/Abbey_Road.mp3') }
37
+ let(:song2) { File.expand_path('~/Music/Rock/Beatles/Sgt_Pepper.mp3') }
38
+ let(:song3) { File.expand_path('~/Music/Rock/Eagles/Hotel_California.ogg') }
50
39
 
51
40
  before do
52
41
  [song1, song2, song3].each do |song|
53
42
  FileUtils.mkdir_p(File.dirname(song))
54
43
  FileUtils.touch(song)
55
- Dir.chdir('/home/xavier')
44
+ Dir.chdir(File.expand_path('~'))
56
45
  end
46
+ File.exists?(song1).should be_true
57
47
  end
58
48
 
59
49
  it "generates a non-empty song list" do
60
- jb.user_config.songs.should_not be_nil
61
- jb.user_config.songs.should_not be_empty
62
- jb.user_config.songs.length.should == 3
63
- jb.user_config.songs.should include(/Abbey_Road.mp3/)
50
+ jb.songs.should_not be_nil
51
+ jb.songs.should_not be_empty
52
+ jb.songs.length.should == 3
53
+ jb.songs.should include(/Abbey_Road.mp3/)
54
+ end
55
+
56
+ it "can quit" do
57
+ jb.should_not be_nil
58
+ jb.quit
59
+ end
60
+
61
+ it "calls play_random_song" do
62
+ jb.stub(:play_random_song).and_return(nil)
63
+ jb.should_receive(:play_once)
64
+ jb.play_once
65
+ jb.quit
66
+ end
67
+
68
+ it "has a user_config method" do
69
+ jb.user_config.is_a?(UserConfig)
64
70
  end
65
71
 
66
72
  =begin
@@ -2,6 +2,7 @@ require 'spec_helper'
2
2
  require 'rspec/mocks'
3
3
  require 'fakeweb' # apparently must be required before fakefs
4
4
  FakeWeb.allow_net_connect = false
5
+ gem 'fakefs', require: 'fakefs/safe'
5
6
  require 'fakefs/safe'
6
7
  require 'jimmy_jukebox/song_loader'
7
8
 
@@ -13,69 +14,58 @@ describe JimmyJukebox::SongLoader do
13
14
  # File.directory?("/home").should be_false
14
15
  #end
15
16
 
16
- before(:all) do
17
- #ARGV.delete_if { |val| true }
18
- ARGV.clear
19
- #ARGV.pop
20
- end
21
-
22
17
  before(:each) do
18
+ ARGV.clear
23
19
  @sl = JimmyJukebox::SongLoader
24
20
  end
25
21
 
26
22
  describe "#create_save_dir" do
23
+ include FakeFS::SpecHelpers
27
24
 
28
25
  it "should create a directory" do
29
- FakeFS do
30
- topdir = File.join("/home","user_name4","Music")
31
- subdir = File.join(topdir, "rock", "Beatles")
32
- File.directory?(subdir).should be_false
33
- @sl.create_save_dir(subdir)
34
- File.directory?(subdir).should be_true
35
- end
26
+ topdir = File.join("/home","user_name4","Music")
27
+ subdir = File.join(topdir, "rock", "Beatles")
28
+ File.directory?(subdir).should be_false
29
+ @sl.create_save_dir(subdir)
30
+ File.directory?(subdir).should be_true
36
31
  end
37
32
 
38
33
  end
39
34
 
40
35
  describe "#version_of_song_in_any_dir?" do
36
+ include FakeFS::SpecHelpers
41
37
 
42
38
  it "should return true if song in top of directory tree" do
43
- FakeFS do
44
- topdir = "/home/user_name1/Music"
45
- songname = "Paperback_Writer.mp3"
46
- File.directory?(topdir).should be_false
47
- FileUtils.mkdir_p(topdir)
48
- File.directory?(topdir).should be_true
49
- Dir.chdir(topdir)
50
- File.exists?(songname).should be_false
51
- FileUtils.touch(songname)
52
- File.exists?(songname).should be_true
53
- @sl.version_of_song_in_any_dir?(songname,topdir).should be_true
54
- end
39
+ topdir = "/home/user_name1/Music"
40
+ songname = "Paperback_Writer.mp3"
41
+ File.directory?(topdir).should be_false
42
+ FileUtils.mkdir_p(topdir)
43
+ File.directory?(topdir).should be_true
44
+ Dir.chdir(topdir)
45
+ File.exists?(songname).should be_false
46
+ FileUtils.touch(songname)
47
+ File.exists?(songname).should be_true
48
+ @sl.version_of_song_in_any_dir?(songname,topdir).should be_true
55
49
  end
56
50
 
57
51
  it "should return true if song in subdirectory" do
58
- FakeFS do
59
- topdir = "/home/user_name2/Music"
60
- subdir = File.join(topdir, "rock", "Beatles")
61
- songname = "Paperback_Writer.mp3"
62
- File.directory?(subdir).should be_false
63
- FileUtils.mkdir_p(subdir)
64
- FileUtils.touch(File.join(subdir, songname))
65
- File.exists?(File.join(subdir, songname)).should be_true
66
- @sl.version_of_song_in_any_dir?(songname,subdir).should be_true
67
- end
52
+ topdir = "/home/user_name2/Music"
53
+ subdir = File.join(topdir, "rock", "Beatles")
54
+ songname = "Paperback_Writer.mp3"
55
+ File.directory?(subdir).should be_false
56
+ FileUtils.mkdir_p(subdir)
57
+ FileUtils.touch(File.join(subdir, songname))
58
+ File.exists?(File.join(subdir, songname)).should be_true
59
+ @sl.version_of_song_in_any_dir?(songname,subdir).should be_true
68
60
  end
69
61
 
70
62
  it "should return false if song not in directory tree" do
71
- FakeFS do
72
- topdir = "/home/user_name3/Music"
73
- subdir = File.join(topdir, "rock", "Beatles")
74
- songname = "Paperback_Writer.mp3"
75
- FileUtils.mkdir_p(subdir)
76
- File.exists?(File.join(subdir, songname)).should be_false
77
- @sl.version_of_song_in_any_dir?(songname,subdir).should be_false
78
- end
63
+ topdir = "/home/user_name3/Music"
64
+ subdir = File.join(topdir, "rock", "Beatles")
65
+ songname = "Paperback_Writer.mp3"
66
+ FileUtils.mkdir_p(subdir)
67
+ File.exists?(File.join(subdir, songname)).should be_false
68
+ @sl.version_of_song_in_any_dir?(songname,subdir).should be_false
79
69
  end
80
70
 
81
71
  end
@@ -121,7 +111,7 @@ describe JimmyJukebox::SongLoader do
121
111
  it "should try to download many songs" do
122
112
  dirname = File.expand_path(@sl.instance_variable_get(:@user_config).default_music_dir + '/JAZZ/Charlie_Christian')
123
113
  @sl.stub!(:version_of_song_in_any_dir?).and_return(false)
124
- @sl.should_receive(:open).exactly(8).times
114
+ @sl.should_receive(:open).exactly(9).times
125
115
  @sl.charlie_christian
126
116
  File.exists?(dirname).should be_true
127
117
  end
@@ -156,6 +146,7 @@ describe JimmyJukebox::SongLoader do
156
146
  describe "#dizzy_gillespie with dirname" do
157
147
 
158
148
  it "should try to download three songs" do
149
+ pending "have not yet implemented way to specify artist-specific directory"
159
150
  dirname = File.expand_path(@sl.instance_variable_get(:@user_config).default_music_dir + '/JAZZ/Dizzy_Gillespie')
160
151
  @sl.stub!(:version_of_song_in_any_dir?).and_return(false)
161
152
  @sl.should_receive(:open).exactly(3).times
@@ -163,16 +154,16 @@ describe JimmyJukebox::SongLoader do
163
154
  end
164
155
 
165
156
  it "should successfully download three songs" do
166
- pending("use FakeWeb")
157
+ pending "use FakeWeb"
167
158
  FakeWeb.register_uri(:any, "http://www.archive.org/download/DizzyGillespie-GroovinHigh/02.GroovinHigh.mp3", :response => "/home/james/Music/JAZZ/Dizzy_Gillespie/Groovin' High 1945.mp3")
168
159
  FakeWeb.register_uri(:any, "http://www.archive.org/download/DizzyGillespie-Manteca/01Manteca.ogg", :response => "/home/james/Music/JAZZ/Dizzy_Gillespie/01Manteca.ogg")
169
160
  FakeWeb.register_uri(:any, "http://www.archive.org/download/DizzyGillespieLouisArmstrong-UmbrellaMan/DizzyGillespieLouisArmstrong-UmbrellaMan.mp3", :response => "/home/james/Music/JAZZ/Dizzy_Gillespie/DizzyGillespieLouisArmstrong-UmbrellaMan.mp3")
170
161
  dirname = File.expand_path("/home/user_name6/non-existent-dir")
171
162
  File.exists?(dirname).should be_false
172
163
  @sl.dizzy_gillespie(dirname)
173
- #File.exists?(dirname + "/02.GroovinHigh.mp3").should be_true
174
- #File.exists?(dirname + "/01Manteca.ogg").should be_true
175
- #File.exists?(dirname + "/DizzyGillespieLouisArmstrong-UmbrellaMan.mp3").should be_true
164
+ File.exists?(dirname + "/02.GroovinHigh.mp3").should be_true
165
+ File.exists?(dirname + "/01Manteca.ogg").should be_true
166
+ File.exists?(dirname + "/DizzyGillespieLouisArmstrong-UmbrellaMan.mp3").should be_true
176
167
  FakeWeb.clean_registry
177
168
  end
178
169
 
data/spec/spec_helper.rb CHANGED
@@ -6,36 +6,3 @@ end
6
6
 
7
7
  require 'fakefs/spec_helpers'
8
8
 
9
- # Overriding FakeFS' File.expand_path
10
- # because it delegates to the same class
11
- # method in the REAL file system
12
- module FakeFS
13
- class File
14
- def self.expand_path(*args)
15
- args[0].gsub(/~/,'/home/xavier')
16
- end
17
- end
18
- # Started overriding FileUtils.ln because FakeFS doesn't know about it
19
- # Instead switched to using File.link, which FakeFS knows about
20
- end
21
-
22
- # Overriding File.expand_path
23
- # so it will provide the fake user's
24
- # home directory
25
- class File
26
- def self.expand_path(*args)
27
- args[0].gsub(/~/,'/home/xavier')
28
- end
29
- end
30
-
31
- # Override exec() to prevent songs from actually playing
32
- # Instead, start a brief sleep process
33
- #module Kernel
34
- # alias :real_exec :exec
35
- #
36
- # def exec(*cmd)
37
- # real_exec("sleep 0.2")
38
- # end
39
- #end
40
-
41
-
@@ -27,7 +27,7 @@ describe UserConfig do
27
27
  describe "#top_music_dir" do
28
28
 
29
29
  it "should parse '~/Music'" do
30
- UserConfig.top_music_dir("~/Music").should == "/home/xavier/Music"
30
+ UserConfig.top_music_dir("~/Music").should == File.expand_path("~/Music")
31
31
  end
32
32
 
33
33
  it "should parse '/home/xavier/Music'" do
@@ -35,15 +35,15 @@ describe UserConfig do
35
35
  end
36
36
 
37
37
  it "should parse '~/Music/Rock/The_Eagles/hotel_california.mp3'" do
38
- UserConfig.top_music_dir("~/Music/Rock/The_Eagles/hotel_california.mp3").should == "/home/xavier/Music"
38
+ UserConfig.top_music_dir("~/Music/Rock/The_Eagles/hotel_california.mp3").should == File.expand_path("~/Music")
39
39
  end
40
40
 
41
41
  it "should parse '~/Music/Rock/The Eagles/Hotel California.mp3'" do
42
- UserConfig.top_music_dir("~/Music/Rock/The Eagles/Hotel California.mp3").should == "/home/xavier/Music"
42
+ UserConfig.top_music_dir("~/Music/Rock/The Eagles/Hotel California.mp3").should == File.expand_path("~/Music")
43
43
  end
44
44
 
45
45
  it "should parse '~/My Music'" do
46
- UserConfig.top_music_dir("~/My Music").should == "/home/xavier/My Music"
46
+ UserConfig.top_music_dir("~/My Music").should == File.expand_path("~/My Music")
47
47
  end
48
48
 
49
49
  end
@@ -64,14 +64,30 @@ describe UserConfig do
64
64
 
65
65
  end
66
66
 
67
- context "with songs" do
67
+ context "with songs in ~/Music" do
68
+
69
+ before(:each) do
70
+ FileUtils.mkdir_p File.expand_path("~/Music")
71
+ FileUtils.touch File.expand_path("~/Music/Yellow_Submarine.mp3")
72
+ end
73
+
74
+ it "finds songs" do
75
+ uc.songs.should_not be_empty
76
+ uc.songs.length.should == 1
77
+ end
78
+
79
+ end
80
+
81
+ context "with songs in ~/Music subdirectory" do
68
82
 
69
83
  before do
70
- FileUtils.mkdir_p "/home/xavier/Music"
71
- FileUtils.touch "/home/xavier/Music/Yellow_Submarine.mp3"
84
+ FileUtils.mkdir_p File.expand_path("~/Music/ROCK/Beatles")
85
+ FileUtils.touch File.expand_path("~/Music/ROCK/Beatles/Yellow_Submarine.mp3")
72
86
  end
73
87
 
74
88
  it "finds songs" do
89
+ File.directory?(File.expand_path("~/Music/ROCK/Beatles")).should be_true
90
+ p uc.songs.to_s
75
91
  uc.songs.should_not be_empty
76
92
  uc.songs.length.should == 1
77
93
  end
metadata CHANGED
@@ -1,125 +1,114 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jimmy_jukebox
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.4.2
4
+ version: 0.4.3
5
+ prerelease:
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-02-22 00:00:00.000000000 Z
12
+ date: 2013-02-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- version_requirements: !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
17
18
  requirements:
18
- - - ">="
19
+ - - ! '>='
19
20
  - !ruby/object:Gem::Version
20
- version: !binary |-
21
- MA==
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
22
25
  none: false
23
- requirement: !ruby/object:Gem::Requirement
24
26
  requirements:
25
- - - ">="
27
+ - - ! '>='
26
28
  - !ruby/object:Gem::Version
27
- version: !binary |-
28
- MA==
29
- none: false
30
- prerelease: false
31
- type: :development
29
+ version: '0'
32
30
  - !ruby/object:Gem::Dependency
33
31
  name: rspec-core
34
- version_requirements: !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
35
34
  requirements:
36
- - - ">="
35
+ - - ! '>='
37
36
  - !ruby/object:Gem::Version
38
- version: !binary |-
39
- MA==
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
40
41
  none: false
41
- requirement: !ruby/object:Gem::Requirement
42
42
  requirements:
43
- - - ">="
43
+ - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: !binary |-
46
- MA==
47
- none: false
48
- prerelease: false
49
- type: :development
45
+ version: '0'
50
46
  - !ruby/object:Gem::Dependency
51
47
  name: rspec-mocks
52
- version_requirements: !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
53
50
  requirements:
54
- - - ">="
51
+ - - ! '>='
55
52
  - !ruby/object:Gem::Version
56
- version: !binary |-
57
- MA==
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
58
57
  none: false
59
- requirement: !ruby/object:Gem::Requirement
60
58
  requirements:
61
- - - ">="
59
+ - - ! '>='
62
60
  - !ruby/object:Gem::Version
63
- version: !binary |-
64
- MA==
65
- none: false
66
- prerelease: false
67
- type: :development
61
+ version: '0'
68
62
  - !ruby/object:Gem::Dependency
69
63
  name: rspec-expectations
70
- version_requirements: !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
71
66
  requirements:
72
- - - ">="
67
+ - - ! '>='
73
68
  - !ruby/object:Gem::Version
74
- version: !binary |-
75
- MA==
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
76
73
  none: false
77
- requirement: !ruby/object:Gem::Requirement
78
74
  requirements:
79
- - - ">="
75
+ - - ! '>='
80
76
  - !ruby/object:Gem::Version
81
- version: !binary |-
82
- MA==
83
- none: false
84
- prerelease: false
85
- type: :development
77
+ version: '0'
86
78
  - !ruby/object:Gem::Dependency
87
79
  name: fakefs
88
- version_requirements: !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
89
82
  requirements:
90
- - - ">="
83
+ - - ! '>='
91
84
  - !ruby/object:Gem::Version
92
- version: !binary |-
93
- MA==
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
94
89
  none: false
95
- requirement: !ruby/object:Gem::Requirement
96
90
  requirements:
97
- - - ">="
91
+ - - ! '>='
98
92
  - !ruby/object:Gem::Version
99
- version: !binary |-
100
- MA==
101
- none: false
102
- prerelease: false
103
- type: :development
93
+ version: '0'
104
94
  - !ruby/object:Gem::Dependency
105
95
  name: fakeweb
106
- version_requirements: !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
107
98
  requirements:
108
- - - ">="
99
+ - - ! '>='
109
100
  - !ruby/object:Gem::Version
110
- version: !binary |-
111
- MA==
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
112
105
  none: false
113
- requirement: !ruby/object:Gem::Requirement
114
106
  requirements:
115
- - - ">="
107
+ - - ! '>='
116
108
  - !ruby/object:Gem::Version
117
- version: !binary |-
118
- MA==
119
- none: false
120
- prerelease: false
121
- type: :development
122
- description: jimmy_jukebox plays random MP3 & OGG songs under a directory (or set of directories) and can download music
109
+ version: '0'
110
+ description: jimmy_jukebox plays random MP3 & OGG songs under a directory (or set
111
+ of directories) and can download music
123
112
  email: james@jameslavin.com
124
113
  executables:
125
114
  - play_jukebox
@@ -162,6 +151,7 @@ files:
162
151
  - lib/jimmy_jukebox/songs/CountBasie.yml
163
152
  - lib/jimmy_jukebox/songs/ArchibaldCampBanjo.yml
164
153
  - lib/jimmy_jukebox/songs/SidneyBechet.yml
154
+ - lib/jimmy_jukebox/songs/Beethoven.yml
165
155
  - lib/jimmy_jukebox/songs/JamesPJohnson.yml
166
156
  - lib/jimmy_jukebox/songs/JellyRollMorton.yml
167
157
  - lib/jimmy_jukebox/songs/Ragtime.yml
@@ -169,39 +159,41 @@ files:
169
159
  - spec/jimmy_jukebox_spec.rb
170
160
  - spec/song_loader_spec.rb
171
161
  - spec/user_config_spec.rb
162
+ - spec/artists_spec.rb
172
163
  - spec/song_spec.rb
173
164
  - spec/spec_helper.rb
174
165
  - bin/play_jukebox
175
166
  - bin/load_jukebox
176
167
  homepage: https://github.com/JamesLavin/jimmy_jukebox
177
168
  licenses: []
178
- post_install_message: I really hope you enjoy the great jazz downloadable using this gem!
169
+ post_install_message: I really hope you enjoy the great jazz downloadable using this
170
+ gem!
179
171
  rdoc_options: []
180
172
  require_paths:
181
173
  - lib
182
174
  required_ruby_version: !ruby/object:Gem::Requirement
175
+ none: false
183
176
  requirements:
184
- - - ">="
177
+ - - ! '>='
185
178
  - !ruby/object:Gem::Version
186
- version: !binary |-
187
- MA==
188
- none: false
179
+ version: '0'
189
180
  required_rubygems_version: !ruby/object:Gem::Requirement
181
+ none: false
190
182
  requirements:
191
- - - ">="
183
+ - - ! '>='
192
184
  - !ruby/object:Gem::Version
193
- version: !binary |-
194
- MA==
195
- none: false
185
+ version: '0'
196
186
  requirements: []
197
187
  rubyforge_project: jimmy_jukebox
198
- rubygems_version: 1.8.24
199
- signing_key:
188
+ rubygems_version: 1.8.23
189
+ signing_key:
200
190
  specification_version: 3
201
191
  summary: plays your MP3 & OGG files and lets you easily download music
202
192
  test_files:
203
193
  - spec/jimmy_jukebox_spec.rb
204
194
  - spec/song_loader_spec.rb
205
195
  - spec/user_config_spec.rb
196
+ - spec/artists_spec.rb
206
197
  - spec/song_spec.rb
207
198
  - spec/spec_helper.rb
199
+ has_rdoc: