jimmy_jukebox 0.2.6 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
data/bin/jload_jukebox CHANGED
@@ -1,29 +1,3 @@
1
1
  #!/usr/bin/env jruby
2
2
 
3
- lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
- $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
- require 'jimmy_jukebox/song_loader'
6
- include JimmyJukebox
7
-
8
- require 'jimmy_jukebox/artists'
9
- include Artists
10
-
11
- def no_argv0
12
- puts "You must select an artist to use 'load_jukebox'."
13
- puts "For example: 'load_jukebox at' to load Art Tatum"
14
- puts "Another example: 'load_jukebox dr' to load Django Reinhardt"
15
- exit
16
- end
17
-
18
- def invalid_artist
19
- puts "No action taken in response to your command 'load_jukebox #{ARGV[0]}'."
20
- puts "JimmyJukebox does not recognize '#{ARGV[0]}'. You must select a valid artist."
21
- puts "For example, valid artists include: 'bh' for Billie Holiday, 'cb' for Count Basie, and 'lh' for Lionel Hampton"
22
- puts "Please see the README for a complete list of valid artists."
23
- exit
24
- end
25
-
26
- no_argv0 unless ARGV[0]
27
- invalid_artist unless JAZZ_ARTISTS.has_key?(ARGV[0].to_sym)
28
- JimmyJukebox::SongLoader.send(JAZZ_ARTISTS[ARGV[0].to_sym])
29
-
3
+ require File.dirname(__FILE__) + '/../lib/jimmy_jukebox/load_jukebox_code.rb'
data/bin/jplay_jukebox CHANGED
@@ -1,49 +1,21 @@
1
1
  #!/usr/bin/env jruby
2
- require 'readline'
3
-
4
- lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
5
- $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
6
- require 'jimmy_jukebox'
7
- include JimmyJukebox
8
-
9
- jj = Jukebox.new
10
2
 
11
- play_loop_thread = Thread.new do
12
- jj.play_loop
13
- end
3
+ require 'readline'
14
4
 
15
- display_string = "Press 'p' to (un)pause, 'q' to quit, or 's' to skip the song"
16
5
  begin
17
- while true do
18
- puts display_string
19
- line = Readline.readline('> ', true)
20
- case line.strip
21
- when "q"
22
- puts "Quit requested"
23
- jj.quit
24
- Thread.main.exit
25
- when "p"
26
- if play_loop_thread && jj.current_song_paused
27
- puts "Unpause requested"
28
- jj.unpause_current_song
29
- elsif play_loop_thread
30
- puts "Pause requested"
31
- jj.pause_current_song
32
- else
33
- raise "Can't find play_loop_thread"
34
- end
35
- puts display_string
36
- when "s"
37
- puts "Skip song requested"
38
- jj.skip_song
39
- else
40
- puts display_string
41
- end
6
+ #Gem::Specification.find_by_name('spoon') # Gem.available?('spoon')
7
+ #gem 'spoon'
8
+ if (defined?(JRUBY_VERSION) || RUBY_PLATFORM == 'java')
9
+ require 'rubygems'
10
+ require 'spoon'
42
11
  end
43
- rescue Interrupt => e
44
- puts "\nMusic terminated by user"
12
+ rescue LoadError
13
+ puts "*** You must install the 'spoon' gem to use JimmyJukebox on JRuby ***"
45
14
  exit
46
15
  end
47
16
 
48
- play_loop_thread.join
17
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
18
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
19
+ require 'jimmy_jukebox'
20
+ include JimmyJukebox
49
21
 
data/bin/load_jukebox CHANGED
@@ -1,29 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
- $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
- require 'jimmy_jukebox/song_loader'
6
- include JimmyJukebox
7
-
8
- require 'jimmy_jukebox/artists'
9
- include Artists
10
-
11
- def no_argv0
12
- puts "You must select an artist to use 'load_jukebox'."
13
- puts "For example: 'load_jukebox at' to load Art Tatum"
14
- puts "Another example: 'load_jukebox dr' to load Django Reinhardt"
15
- exit
16
- end
17
-
18
- def invalid_artist
19
- puts "No action taken in response to your command 'load_jukebox #{ARGV[0]}'."
20
- puts "JimmyJukebox does not recognize '#{ARGV[0]}'. You must select a valid artist."
21
- puts "For example, valid artists include: 'bh' for Billie Holiday, 'cb' for Count Basie, and 'lh' for Lionel Hampton"
22
- puts "Please see the README for a complete list of valid artists."
23
- exit
24
- end
25
-
26
- no_argv0 unless ARGV[0]
27
- invalid_artist unless JAZZ_ARTISTS.has_key?(ARGV[0].to_sym)
28
- JimmyJukebox::SongLoader.send(JAZZ_ARTISTS[ARGV[0].to_sym])
29
-
3
+ require File.dirname(__FILE__) + '/../lib/jimmy_jukebox/load_jukebox_code.rb'
data/bin/play_jukebox CHANGED
@@ -6,44 +6,3 @@ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
6
6
  require 'jimmy_jukebox'
7
7
  include JimmyJukebox
8
8
 
9
- jj = Jukebox.new
10
-
11
- play_loop_thread = Thread.new do
12
- jj.play_loop
13
- end
14
-
15
- display_string = "Press 'p' to (un)pause, 'q' to quit, or 's' to skip the song"
16
- begin
17
- while true do
18
- puts display_string
19
- line = Readline.readline('> ', true)
20
- case line.strip
21
- when "q"
22
- puts "Quit requested"
23
- jj.quit
24
- Thread.main.exit
25
- when "p"
26
- if play_loop_thread && jj.current_song_paused
27
- puts "Unpause requested"
28
- jj.unpause_current_song
29
- elsif play_loop_thread
30
- puts "Pause requested"
31
- jj.pause_current_song
32
- else
33
- raise "Can't find play_loop_thread"
34
- end
35
- puts display_string
36
- when "s"
37
- puts "Skip song requested"
38
- jj.skip_song
39
- else
40
- puts display_string
41
- end
42
- end
43
- rescue Interrupt => e
44
- puts "\nMusic terminated by user"
45
- exit
46
- end
47
-
48
- play_loop_thread.join
49
-
@@ -0,0 +1,83 @@
1
+ module JimmyJukebox
2
+
3
+ module Jukebox
4
+
5
+ class << Jukebox
6
+
7
+ attr_accessor :current_song, :continuous_play
8
+
9
+ end
10
+
11
+ def self.play_loop
12
+ @continuous_play = true
13
+ while @continuous_play do
14
+ play_once
15
+ end
16
+ end
17
+
18
+ def self.play_once
19
+ begin
20
+ play_random_song
21
+ rescue SystemExit, Interrupt => e
22
+ terminate_current_song
23
+ puts "\nMusic terminated by user"
24
+ exit
25
+ end
26
+ end
27
+
28
+ def self.quit
29
+ stop_looping
30
+ terminate_current_song
31
+ end
32
+
33
+ def self.skip_song
34
+ if @current_song
35
+ puts "Terminating #{@current_song.music_file}"
36
+ terminate_current_song
37
+ else
38
+ raise "No @current_song"
39
+ end
40
+ end
41
+
42
+ def self.pause_current_song
43
+ @current_song.pause
44
+ end
45
+
46
+ def self.unpause_current_song
47
+ @current_song.unpause
48
+ end
49
+
50
+ def self.stop_looping
51
+ @continuous_play = false
52
+ end
53
+
54
+ def self.songs
55
+ user_config.songs
56
+ end
57
+
58
+ def self.play_random_song
59
+ #terminate_current_song
60
+ raise "JimmyJukebox has no songs to play!" if songs.length == 0
61
+ @current_song = Song.new( songs[rand(songs.length)] )
62
+ @current_song.play(user_config)
63
+ @current_song = nil # ????
64
+ end
65
+
66
+ def self.terminate_current_song
67
+ if @current_song
68
+ puts "Terminating #{@current_song.music_file}"
69
+ @current_song.terminate
70
+ #@current_song = nil
71
+ else
72
+ puts "No song is currently playing"
73
+ end
74
+ end
75
+
76
+ def self.user_config
77
+ @user_config = UserConfig.new unless @user_config
78
+ @user_config
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path(File.dirname(__FILE__) + '/..')
2
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
3
+ require 'jimmy_jukebox/song_loader'
4
+ include JimmyJukebox
5
+
6
+ require 'jimmy_jukebox/artists'
7
+ include Artists
8
+
9
+ def no_argv0
10
+ puts "You must select an artist to use 'load_jukebox'."
11
+ puts "For example: 'load_jukebox at' to load Art Tatum"
12
+ puts "Another example: 'load_jukebox dr' to load Django Reinhardt"
13
+ exit
14
+ end
15
+
16
+ def invalid_artist
17
+ puts "No action taken in response to your command 'load_jukebox #{ARGV[0]}'."
18
+ puts "JimmyJukebox does not recognize '#{ARGV[0]}'. You must select a valid artist."
19
+ puts "For example, valid artists include: 'bh' for Billie Holiday, 'cb' for Count Basie, and 'lh' for Lionel Hampton"
20
+ puts "Please see the README for a complete list of valid artists."
21
+ exit
22
+ end
23
+
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
+
@@ -0,0 +1,111 @@
1
+ module JimmyJukebox
2
+
3
+ class Song
4
+
5
+ attr_reader :paused, :music_file
6
+ attr_accessor :player, :playing_pid
7
+
8
+ def initialize(music_file)
9
+ set_music_file(music_file)
10
+ @paused = false
11
+ @playing_pid = nil
12
+ end
13
+
14
+ def set_music_file(music_file)
15
+ if music_file =~ /\.mp3$/i || music_file =~ /\.ogg$/i
16
+ @music_file = music_file
17
+ else
18
+ raise "You can create a song only with an .mp3 or .ogg file"
19
+ end
20
+ end
21
+
22
+ def pause
23
+ @paused = true
24
+ # jruby doesn't seem to handle system() correctly
25
+ # trying backticks
26
+ # system("kill -s STOP #{@playing_pid}") if @playing_pid
27
+ `kill -s STOP #{@playing_pid}` if @playing_pid
28
+ end
29
+
30
+ def unpause
31
+ @paused = false
32
+ # jruby doesn't seem to handle system() correctly
33
+ # trying backticks
34
+ #system("kill -s CONT #{@playing_pid}") if @playing_pid
35
+ `kill -s CONT #{@playing_pid}` if @playing_pid
36
+ end
37
+
38
+ def delete
39
+ # without temp var, next song could start playing
40
+ # in another thread and wrong file could be deleted
41
+ file_to_delete = @music_file
42
+ terminate
43
+ File.delete(file_to_delete)
44
+ end
45
+
46
+ def terminate
47
+ @paused = false
48
+ #`killall #{@player}`
49
+ @player = nil
50
+ # killing processes seems problematic in JRuby
51
+ # I've tried several approaches, and nothing seems reliable
52
+ #Process.kill("SIGKILL",@playing_pid) if @playing_pid
53
+ #Process.kill("SIGTERM",@playing_pid) if @playing_pid
54
+ `kill #{@playing_pid}` if @playing_pid
55
+ @playing_pid = nil
56
+ end
57
+
58
+ def set_player(user_config)
59
+ if @music_file =~ /\.mp3$/i
60
+ @player = user_config.mp3_player
61
+ elsif @music_file =~ /\.ogg$/i
62
+ @player = user_config.ogg_player
63
+ end
64
+ raise "Attempted to play a file format this program cannot play" unless @player
65
+ end
66
+
67
+ def play(user_config)
68
+ set_player(user_config)
69
+ process_status = play_with_player
70
+ process_status.exitstatus.to_i == 0 ? (@playing_pid = nil) : (raise "Experienced a problem playing a song")
71
+ end
72
+
73
+ def play_with_player
74
+ puts "Press Ctrl-C to stop the music and exit this program"
75
+ puts "Now playing '#{@music_file}'"
76
+ puts "#{@player} \"#{File.expand_path(@music_file)}\""
77
+ system_yield_pid(@player, File.expand_path(@music_file)) do |pid|
78
+ @playing_pid = pid
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ # make system call and get pid so you can terminate process
85
+ def system_yield_pid(player, filename)
86
+ # would like to use Process.respond_to?(:fork) but JRuby mistakenly returns true
87
+ if (defined?(JRUBY_VERSION) || RUBY_PLATFORM == 'java')
88
+ pid = Spoon.spawnp("#{player}", "#{filename}")
89
+ else
90
+ begin
91
+ pid = fork do # creates and runs block in subprocess (which will terminate with status 0), capture subprocess pid
92
+ exec(player,filename) # replaces current process with system call
93
+ exit! 127 # exit process and return exit status 127; should never be reached
94
+ end
95
+ rescue NotImplementedError
96
+ raise "*** fork()...exec() not supported ***"
97
+ end
98
+ end
99
+ yield pid if block_given? # call block, passing in the subprocess pid
100
+ #if pid
101
+ # puts "pid: #{pid}"
102
+ # puts "current_song: #{Jukebox.current_song.inspect}"
103
+ #else
104
+ # puts "No process id (pid)!"
105
+ # raise "@current_song: #{Jukebox.current_song.inspect}"
106
+ #end
107
+ Process.waitpid(pid) # Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object
108
+ $? # return Process::Status object with instance methods .stopped?, .exited?, .exitstatus; see: http://www.ruby-doc.org/core/classes/Process/Status.html
109
+ end
110
+
111
+ end
@@ -0,0 +1,41 @@
1
+ jj = Jukebox
2
+
3
+ play_loop_thread = Thread.new do
4
+ jj.play_loop
5
+ end
6
+
7
+ display_string = "Press 'p' to (un)pause, 'q' to quit, or 's' to skip the song"
8
+ begin
9
+ while true do
10
+ puts display_string
11
+ line = Readline.readline('> ', true)
12
+ case line.strip
13
+ when "q"
14
+ puts "Quit requested"
15
+ jj.quit
16
+ Thread.main.exit
17
+ when "p"
18
+ if play_loop_thread && jj.current_song.paused
19
+ puts "Unpause requested"
20
+ jj.unpause_current_song
21
+ elsif play_loop_thread
22
+ puts "Pause requested"
23
+ jj.pause_current_song
24
+ else
25
+ raise "Can't find play_loop_thread"
26
+ end
27
+ puts display_string
28
+ when "s"
29
+ puts "Skip song requested"
30
+ jj.skip_song
31
+ else
32
+ puts display_string
33
+ end
34
+ end
35
+ rescue Interrupt => e
36
+ puts "\nMusic terminated by user"
37
+ exit
38
+ end
39
+
40
+ play_loop_thread.join
41
+
@@ -1,3 +1,3 @@
1
1
  module JimmyJukebox
2
- VERSION = '0.2.6'
2
+ VERSION = '0.3.6'
3
3
  end
data/lib/jimmy_jukebox.rb CHANGED
@@ -1,120 +1,7 @@
1
- module JimmyJukebox
1
+ require 'jimmy_jukebox/user_config'
2
+ require 'jimmy_jukebox/song'
3
+ require 'jimmy_jukebox/jukebox'
2
4
 
3
- # make system call and get pid so you can terminate process
4
- def system_yield_pid(*cmd)
5
- # would like to use Process.respond_to?(:fork) but JRuby mistakenly returns true
6
- begin
7
- pid = fork do # creates and runs block in subprocess (which will terminate with status 0), capture subprocess pid
8
- exec(*cmd) # replaces current process with system call
9
- exit! 127 # exit process and return exit status 127; should never be reached
10
- end
11
- rescue NotImplementedError
12
- require 'rubygems'
13
- require 'spoon'
14
- pid = Spoon.spawnp(*cmd)
15
- #raise "*** fork() not supported ***" unless Process.respond_to?(:fork)
16
- end
17
- yield pid if block_given? # call block, passing in the subprocess pid
18
- Process.waitpid(pid) # Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object
19
- $? # return Process::Status object with instance methods .stopped?, .exited?, .exitstatus; see: http://www.ruby-doc.org/core/classes/Process/Status.html
20
- end
5
+ include JimmyJukebox
21
6
 
22
- class Jukebox
23
-
24
- require 'jimmy_jukebox/user_config'
25
-
26
- attr_reader :loop, :current_song_paused, :playing_pid
27
-
28
- def initialize
29
- @user_config = UserConfig.new
30
- end
31
-
32
- def play_loop
33
- @loop = true
34
- while @loop do
35
- play
36
- end
37
- end
38
-
39
- def play
40
- begin
41
- play_random_song(@user_config.songs)
42
- rescue SystemExit, Interrupt => e
43
- terminate_current_song
44
- puts "\nMusic terminated by user"
45
- exit
46
- end
47
- end
48
-
49
- def quit
50
- stop_looping
51
- terminate_current_song
52
- end
53
-
54
- def skip_song
55
- terminate_current_song
56
- end
57
-
58
- def pause_current_song
59
- @current_song_paused = true
60
- # jruby doesn't seem to handle system() correctly
61
- # trying backticks
62
- # system("kill -s STOP #{@playing_pid}") if @playing_pid
63
- `kill -s STOP #{@playing_pid}` if @playing_pid
64
- end
65
-
66
- def unpause_current_song
67
- @current_song_paused = false
68
- # jruby doesn't seem to handle system() correctly
69
- # trying backticks
70
- #system("kill -s CONT #{@playing_pid}") if @playing_pid
71
- `kill -s CONT #{@playing_pid}` if @playing_pid
72
- end
73
-
74
- private
75
-
76
- def stop_looping
77
- @loop = false
78
- end
79
-
80
- def play_random_song(songs)
81
- terminate_current_song
82
- raise "JimmyJukebox has no songs to play!" if songs.length == 0
83
- music_file = songs[rand(songs.length)]
84
- play_file(music_file)
85
- end
86
-
87
- def terminate_current_song
88
- if @playing_pid
89
- @current_song_paused = false
90
- # killing processes seems problematic in JRuby
91
- # I've tried several approaches, and nothing seems reliable
92
- Process.kill("SIGKILL",@playing_pid)
93
- #Process.kill("SIGTERM",@playing_pid)
94
- #`kill #{@playing_pid}` if @playing_pid
95
- @playing_pid = nil
96
- end
97
- end
98
-
99
- def play_file(music_file)
100
- # TODO: refactor the duplicate code below into a method
101
- if music_file =~ /\.mp3$/i && @user_config.mp3_player
102
- process_status = play_file_with(music_file, @user_config.mp3_player)
103
- elsif music_file =~ /\.ogg$/i && @user_config.ogg_player
104
- process_status = play_file_with(music_file, @user_config.ogg_player)
105
- else
106
- raise "Attempted to play a file format this program cannot play"
107
- end
108
- process_status.exitstatus.to_i == 0 ? (@playing_pid = nil) : (raise "Experienced a problem playing a song")
109
- end
110
-
111
- def play_file_with(music_file,player)
112
- puts "Press Ctrl-C to stop the music and exit this program"
113
- system_yield_pid(player, File.expand_path(music_file)) do |pid|
114
- @playing_pid = pid
115
- end
116
- end
117
-
118
- end
119
-
120
- end
7
+ require 'jimmy_jukebox/user_interface'
@@ -3,29 +3,20 @@ require 'fakefs/safe'
3
3
  require 'jimmy_jukebox'
4
4
  include JimmyJukebox
5
5
 
6
- # Override exec() to prevent songs from actually playing
7
- # Instead, start a brief sleep process
8
- module Kernel
9
- alias :real_exec :exec
10
-
11
- def exec(*cmd)
12
- real_exec("sleep 0.2")
13
- end
14
- end
15
-
16
6
  describe Jukebox do
17
7
 
18
8
  before(:all) do
19
- #ARGV.clear
20
- ARGV.pop
9
+ ARGV.clear
10
+ #ARGV.pop
21
11
  end
22
12
 
13
+ let(:uc) { double('user_config').as_null_object }
14
+
23
15
  context "with no command line parameter" do
24
16
 
25
- it "can be instantiated" do
26
- jj = Jukebox.new
27
- jj.should_not be_nil
28
- jj.quit
17
+ it "exists" do
18
+ Jukebox.should_not be_nil
19
+ Jukebox.quit
29
20
  end
30
21
 
31
22
  #it "raises exception when no songs available"
@@ -34,102 +25,172 @@ describe Jukebox do
34
25
  # end.should raise_error
35
26
  #end
36
27
 
28
+ it "has a user_config method" do
29
+ Jukebox.user_config.is_a?(UserConfig)
30
+ end
31
+
32
+ it "has a @user_config instance variable" do
33
+ Jukebox.instance_variable_get(:@user_config).is_a?(UserConfig)
34
+ end
35
+
37
36
  it "generates a non-empty song list" do
38
- jj = Jukebox.new
39
- jj.instance_variable_get(:@user_config).songs.should_not be_nil
40
- jj.instance_variable_get(:@user_config).songs.should_not be_empty
41
- jj.instance_variable_get(:@user_config).songs.length.should be > 0
37
+ Jukebox.user_config.songs.should_not be_nil
38
+ Jukebox.user_config.songs.should_not be_empty
39
+ Jukebox.user_config.songs.length.should be > 0
42
40
  end
43
41
 
44
42
  it "generates a non-empty song list with only mp3 & ogg files" do
45
- jj = Jukebox.new
46
- jj.instance_variable_get(:@user_config).songs.each do |song|
43
+ Jukebox.user_config.songs.each do |song|
47
44
  song.should match(/.*\.mp3|.*\.ogg/i)
48
45
  end
49
46
  end
50
47
 
51
- it "can play" do
52
- jj = Jukebox.new
53
- thread = Thread.new do
54
- jj.play
48
+ describe "#play_once" do
49
+
50
+ it "should call play_random_song" do
51
+ Jukebox.should_receive(:play_random_song)
52
+ Jukebox.play_once
55
53
  end
56
- sleep 0.2
57
- jj.instance_variable_get(:@playing_pid).should_not be_nil
58
- jj.should_receive(:terminate_current_song)
59
- jj.quit
60
- end
61
54
 
62
- it "can play_loop" do
63
- jj = Jukebox.new
64
- thread = Thread.new do
65
- jj.play_loop
55
+ it "should have a current_song" do
56
+ jj = Jukebox
57
+ uc.stub(:mp3_player) {"play"}
58
+ uc.stub(:ogg_player) {"play"}
59
+ thread = Thread.new do
60
+ Jukebox.play_once
61
+ end
62
+ sleep 0.1
63
+ jj.current_song.is_a?(Song)
64
+ thread.exit
66
65
  end
67
- sleep 0.1
68
- song1 = jj.playing_pid
69
- song1.should_not be_nil
70
- jj.loop.should be_true
71
- sleep 0.2
72
- song2 = jj.playing_pid
73
- song2.should_not be_nil
74
- song2.should_not == song1
75
- jj.quit
76
- end
77
66
 
78
- it "can skip a song" do
79
- jj = Jukebox.new
80
- thread = Thread.new do
81
- jj.play_loop
67
+ it "should have a current_song with a music_file" do
68
+ jj = Jukebox
69
+ uc.stub(:mp3_player) {"play"}
70
+ uc.stub(:ogg_player) {"play"}
71
+ thread = Thread.new do
72
+ Jukebox.play_once
73
+ end
74
+ sleep 0.1
75
+ jj.current_song.music_file.should match /\.mp3$|\.ogg$/
76
+ thread.exit
82
77
  end
83
- sleep 0.2
84
- song_1 = jj.playing_pid
85
- jj.skip_song
86
- sleep 0.2
87
- song_2 = jj.playing_pid
88
- jj.skip_song
89
- sleep 0.2
90
- song_3 = jj.playing_pid
91
- song_1.should_not == song_2 || song_2.should_not == song_3
92
- jj.quit
93
- end
94
78
 
95
- it "can pause the current song" do
96
- jj = Jukebox.new
97
- thread = Thread.new do
98
- jj.play
79
+ it "should have a player" do
80
+ jj = Jukebox
81
+ thread = Thread.new do
82
+ Jukebox.play_once
83
+ end
84
+ sleep 0.1
85
+ jj.current_song.player.should_not be_nil
86
+ thread.exit
87
+ end
88
+
89
+ it "should not have a current_song after song finishes" do
90
+ jj = Jukebox
91
+ thread = Thread.new do
92
+ Jukebox.play_once
93
+ end
94
+ sleep 0.3
95
+ jj.current_song.should be_nil
96
+ thread.exit
99
97
  end
100
- sleep 0.1
101
- song_1 = jj.playing_pid
102
- jj.pause_current_song
103
- song_2 = jj.playing_pid
104
- song_1.should == song_2
105
- jj.current_song_paused.should be_true
106
- jj.quit
98
+
99
+ it "should have a current_song with a playing_pid" do
100
+ jj = Jukebox
101
+ thread = Thread.new do
102
+ jj.play_once
103
+ end
104
+ sleep 0.1
105
+ jj.current_song.playing_pid.should_not be_nil
106
+ #jj.should_receive(:terminate_current_song)
107
+ jj.quit
108
+ thread.exit
109
+ end
110
+
111
+ it "triggers play_random_song" do
112
+ Jukebox.should_receive(:play_random_song)
113
+ Jukebox.play_once
114
+ end
115
+
116
+ it "can pause the current song" do
117
+ thread = Thread.new do
118
+ Jukebox.play_once
119
+ end
120
+ sleep 0.1
121
+ song_1 = Jukebox.current_song.playing_pid
122
+ Jukebox.pause_current_song
123
+ song_2 = Jukebox.current_song.playing_pid
124
+ song_1.should == song_2
125
+ Jukebox.current_song.paused.should be_true
126
+ Jukebox.quit
127
+ thread.exit
128
+ end
129
+
130
+ it "can unpause a paused song" do
131
+ thread = Thread.new do
132
+ Jukebox.play_once
133
+ end
134
+ sleep 0.05
135
+ song_1 = Jukebox.current_song
136
+ Jukebox.current_song.paused.should be_false
137
+ Jukebox.pause_current_song
138
+ song_2 = Jukebox.current_song
139
+ Jukebox.current_song.paused.should be_true
140
+ song_2.should == song_1
141
+ Jukebox.unpause_current_song
142
+ Jukebox.current_song.paused.should be_false
143
+ song_3 = Jukebox.current_song
144
+ Jukebox.current_song.paused.should be_false
145
+ Jukebox.pause_current_song
146
+ song_4 = Jukebox.current_song
147
+ Jukebox.current_song.paused.should be_true
148
+ song_4.should == song_3
149
+ Jukebox.unpause_current_song
150
+ Jukebox.current_song.paused.should be_false
151
+ Jukebox.quit
152
+ thread.exit
153
+ end
154
+
107
155
  end
108
156
 
109
- it "can unpause a paused song" do
110
- jj = Jukebox.new
111
- thread = Thread.new do
112
- jj.play
157
+ describe "#play_loop" do
158
+
159
+ it "plays multiple songs" do
160
+ thread = Thread.new do
161
+ Jukebox.play_loop
162
+ end
163
+ sleep 0.1
164
+ song1 = Jukebox.current_song.playing_pid
165
+ song1.should_not be_nil
166
+ Jukebox.continuous_play.should be_true
167
+ sleep 0.2
168
+ song2 = Jukebox.current_song.playing_pid
169
+ song2.should_not be_nil
170
+ song2.should_not == song1
171
+ Jukebox.quit
172
+ thread.exit
113
173
  end
114
- sleep 0.05
115
- song_1 = jj.playing_pid
116
- jj.current_song_paused.should be_false
117
- jj.pause_current_song
118
- song_2 = jj.playing_pid
119
- jj.current_song_paused.should be_true
120
- song_2.should == song_1
121
- jj.unpause_current_song
122
- jj.current_song_paused.should be_false
123
- song_3 = jj.playing_pid
124
- jj.current_song_paused.should be_false
125
- jj.pause_current_song
126
- song_4 = jj.playing_pid
127
- jj.current_song_paused.should be_true
128
- song_4.should == song_3
129
- jj.unpause_current_song
130
- jj.current_song_paused.should be_false
131
- jj.quit
174
+
175
+ it "can skip a song" do
176
+ thread = Thread.new do
177
+ Jukebox.play_loop
178
+ end
179
+ sleep 0.2
180
+ song_1 = Jukebox.current_song
181
+ Jukebox.skip_song
182
+ sleep 0.2
183
+ song_2 = Jukebox.current_song
184
+ Jukebox.skip_song
185
+ sleep 0.2
186
+ song_3 = Jukebox.current_song
187
+ song_1.should_not == song_2 || song_2.should_not == song_3
188
+ Jukebox.quit
189
+ thread.exit
190
+ end
191
+
132
192
  end
193
+
133
194
  end
134
195
 
135
196
  context "with valid music directory as command line parameter" do
@@ -140,20 +201,20 @@ describe Jukebox do
140
201
  end
141
202
 
142
203
  it "can skip a song" do
143
- jj = Jukebox.new
144
204
  thread = Thread.new do
145
- jj.play_loop
205
+ Jukebox.play_loop
146
206
  end
147
207
  sleep 0.2
148
- song_1 = jj.playing_pid
149
- jj.skip_song
208
+ song_1 = Jukebox.current_song
209
+ Jukebox.skip_song
150
210
  sleep 0.2
151
- song_2 = jj.playing_pid
152
- jj.skip_song
211
+ song_2 = Jukebox.current_song
212
+ Jukebox.skip_song
153
213
  sleep 0.2
154
- song_3 = jj.playing_pid
214
+ song_3 = Jukebox.current_song
155
215
  song_1.should_not == song_2 || song_2.should_not == song_3
156
- jj.quit
216
+ Jukebox.quit
217
+ thread.exit
157
218
  end
158
219
 
159
220
  end
@@ -16,8 +16,8 @@ describe JimmyJukebox::SongLoader do
16
16
 
17
17
  before(:all) do
18
18
  #ARGV.delete_if { |val| true }
19
- #ARGV.clear
20
- ARGV.pop
19
+ ARGV.clear
20
+ #ARGV.pop
21
21
  end
22
22
 
23
23
  before(:each) do
data/spec/song_spec.rb ADDED
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+ require 'jimmy_jukebox/song'
3
+ require 'jimmy_jukebox/user_config'
4
+
5
+ include JimmyJukebox
6
+
7
+ describe Song do
8
+
9
+ before(:each) do
10
+ end
11
+
12
+ describe "#initialize" do
13
+
14
+ it "requires a parameter" do
15
+ expect {Song.new}.to raise_error
16
+ end
17
+
18
+ it "fails if parameter does not end in .mp3 or .ogg" do
19
+ expect {Song.new("/home/bill/music_file")}.to raise_error
20
+ end
21
+
22
+ it "accepts a parameter ending in .mp3" do
23
+ Song.new("/home/bill/music_file.mp3").is_a?(Song)
24
+ end
25
+
26
+ it "accepts a parameter ending in .ogg" do
27
+ Song.new("/home/bill/music_file.ogg").is_a?(Song)
28
+ end
29
+
30
+ it "sets a music file" do
31
+ mf = "/home/bill/Music/JAZZ/billie_holiday.ogg"
32
+ song = Song.new(mf)
33
+ song.music_file.should == mf
34
+ end
35
+
36
+ end
37
+
38
+ describe "#paused" do
39
+
40
+ before(:each) do
41
+ @song = Song.new("~/Music/JAZZ/art_tatum.mp3")
42
+ end
43
+
44
+ it "is initially not paused" do
45
+ @song.paused.should be_false
46
+ end
47
+
48
+ it "is paused after calling #pause" do
49
+ @song.pause
50
+ @song.paused.should be_true
51
+ end
52
+
53
+ it "is unpaused after calling #pause and #unpause" do
54
+ @song.pause
55
+ @song.unpause
56
+ @song.paused.should be_false
57
+ end
58
+
59
+ end
60
+
61
+ describe "#play" do
62
+
63
+ before(:each) do
64
+ @music_file = "~/Music/JAZZ/art_tatum.mp3"
65
+ @song = Song.new(@music_file)
66
+ end
67
+
68
+ let(:uc) { double('user_config').as_null_object }
69
+ let(:ps) { double('process_status').as_null_object}
70
+
71
+ it "calls #play_with_player" do
72
+ ps.stub(:exitstatus).and_return(0)
73
+ @song.should_receive(:play_with_player).and_return(ps)
74
+ uc.stub(:mp3_player) {"play"}
75
+ uc.stub(:ogg_player) {"play"}
76
+ @song.play(uc)
77
+ end
78
+
79
+ it "raises error when exitstatus != 0" do
80
+ ps.stub(:exitstatus).and_return(1)
81
+ @song.should_receive(:play_with_player).and_return(ps)
82
+ uc.stub(:mp3_player) {"play"}
83
+ uc.stub(:ogg_player) {"play"}
84
+ expect{@song.play(uc)}.to raise_error
85
+ end
86
+
87
+ end
88
+
89
+ describe "#play_with_player" do
90
+
91
+ before(:each) do
92
+ @music_file = "~/Music/JAZZ/art_tatum.mp3"
93
+ @song = Song.new(@music_file)
94
+ end
95
+
96
+ let(:uc) { double('user_config').as_null_object }
97
+ let(:ps) { double('process_status').as_null_object}
98
+
99
+ it "calls #system_yield_pid" do
100
+ uc.stub(:mp3_player) {"play"}
101
+ uc.stub(:ogg_player) {"play"}
102
+ @song.set_player(uc)
103
+ @song.should_receive(:system_yield_pid).with("play",File.expand_path(@music_file)).and_return(ps)
104
+ @song.play_with_player
105
+ end
106
+
107
+ it "calls #system_yield_pid and captures playing_pid" do
108
+ pending
109
+ uc.stub(:mp3_player) {"play"}
110
+ uc.stub(:ogg_player) {"play"}
111
+ @song.set_player(uc)
112
+ @song.should_receive(:system_yield_pid).with("play",File.expand_path(@music_file)).and_yield(1469)
113
+ @song.play_with_player
114
+ @song.playing_pid.should == 1469
115
+ end
116
+
117
+ end
118
+
119
+ describe "#playing_pid" do
120
+
121
+ before(:each) do
122
+ @song = Song.new("~/Music/JAZZ/art_tatum.mp3")
123
+ end
124
+
125
+ let(:uc) { double('user_config').as_null_object }
126
+
127
+ it "is initially nil" do
128
+ @song.playing_pid.should be_nil
129
+ end
130
+
131
+ it "is not nil after #play" do
132
+ uc.stub(:mp3_player) {"play"}
133
+ uc.stub(:ogg_player) {"play"}
134
+ thread = Thread.new do
135
+ @song.play(uc)
136
+ end
137
+ sleep 0.1
138
+ @song.playing_pid.should_not be_nil
139
+ end
140
+
141
+ end
142
+
143
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,3 +3,15 @@ RSpec.configure do |config|
3
3
  ARGV.clear
4
4
  end
5
5
  end
6
+
7
+ # Override exec() to prevent songs from actually playing
8
+ # Instead, start a brief sleep process
9
+ module Kernel
10
+ alias :real_exec :exec
11
+
12
+ def exec(*cmd)
13
+ real_exec("sleep 0.2")
14
+ end
15
+ end
16
+
17
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jimmy_jukebox
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 6
10
- version: 0.2.6
10
+ version: 0.3.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - James Lavin
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-22 00:00:00 Z
18
+ date: 2011-09-02 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec
@@ -115,10 +115,14 @@ extra_rdoc_files: []
115
115
  files:
116
116
  - roadmap.txt
117
117
  - LICENSE.txt
118
+ - lib/jimmy_jukebox/load_jukebox_code.rb
119
+ - lib/jimmy_jukebox/jukebox.rb
118
120
  - lib/jimmy_jukebox/song_loader.rb
119
121
  - lib/jimmy_jukebox/user_config.rb
120
122
  - lib/jimmy_jukebox/version.rb
123
+ - lib/jimmy_jukebox/song.rb
121
124
  - lib/jimmy_jukebox/artists.rb
125
+ - lib/jimmy_jukebox/user_interface.rb
122
126
  - lib/jimmy_jukebox.rb
123
127
  - lib/jimmy_jukebox/songs/BennieMoten.yml
124
128
  - lib/jimmy_jukebox/songs/MilesDavis.yml
@@ -148,6 +152,7 @@ files:
148
152
  - spec/user_config_spec.rb
149
153
  - spec/jimmy_jukebox_spec.rb
150
154
  - spec/song_loader_spec.rb
155
+ - spec/song_spec.rb
151
156
  - bin/play_jukebox
152
157
  - bin/load_jukebox
153
158
  - bin/jplay_jukebox
@@ -178,10 +183,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
183
  segments:
179
184
  - 0
180
185
  version: "0"
181
- requirements: []
182
-
186
+ requirements:
187
+ - spoon gem (JRuby only)
183
188
  rubyforge_project: jimmy_jukebox
184
- rubygems_version: 1.8.5
189
+ rubygems_version: 1.8.7
185
190
  signing_key:
186
191
  specification_version: 3
187
192
  summary: plays your MP3 & OGG files and lets you easily download music
@@ -190,3 +195,4 @@ test_files:
190
195
  - spec/user_config_spec.rb
191
196
  - spec/jimmy_jukebox_spec.rb
192
197
  - spec/song_loader_spec.rb
198
+ - spec/song_spec.rb