jimmy_jukebox 0.2.6 → 0.3.6

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/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