jimmy_jukebox 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/bin/play_jukebox CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- if RUBY_ENGINE =~ /jruby/
3
+ $running_jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby') || RUBY_PLATFORM == 'java'
4
+
5
+ if $running_jruby
4
6
  begin
5
7
  require 'spoon'
6
8
  require 'readline'
7
9
  rescue LoadError => e
8
10
  if e.message =~ /spoon/
9
- p "*** You must install the 'spoon' gem to use JimmyJukebox on JRuby ***"
11
+ p "*** You must run 'gem install spoon' before using JimmyJukebox on JRuby ***"
10
12
  exit
11
13
  elsif e.message =~ /readline/
12
14
  p "*** You must install 'readline' to use JimmyJukebox on JRuby ***"
@@ -24,7 +26,7 @@ else
24
26
  p "*** You must install 'readline' or the 'rb-readline' gem to use JimmyJukebox in Ruby ***"
25
27
  exit
26
28
  elsif e.message =~ /posix/ || e.message =~ /spawn/
27
- p "*** You must install the 'posix-spawn' gem to use JimmyJukebox in Ruby ***"
29
+ p "*** You must run 'gem install posix-spawn' before using JimmyJukebox in Ruby ***"
28
30
  exit
29
31
  else
30
32
  raise
@@ -26,6 +26,7 @@ module Artists
26
26
  :lh => "lionel_hampton",
27
27
  :md => "miles_davis",
28
28
  :odjb => "original_dixieland_jazz_band",
29
+ :rt => "ragtime",
29
30
  :rn => "red_norvo",
30
31
  :sb => "sidney_bechet"
31
32
  }
@@ -44,5 +45,4 @@ module Artists
44
45
  value.to_s.split("_").map! { |name_component| name_component.capitalize }.join("") + '.yml'
45
46
  end
46
47
 
47
-
48
48
  end
@@ -8,8 +8,8 @@ module JimmyJukebox
8
8
  class NoCurrentSongException < Exception; end
9
9
  class NoPreviousSongException < Exception; end
10
10
 
11
- attr_accessor :current_song, :continuous_play
12
- attr_writer :user_config, :previous_song, :next_song, :playing
11
+ attr_accessor :current_song, :continuous_play, :songs_played
12
+ attr_writer :user_config, :next_song, :playing
13
13
 
14
14
  def initialize(new_user_config = UserConfig.new, continuous_play = true)
15
15
  self.user_config = new_user_config
@@ -19,7 +19,7 @@ module JimmyJukebox
19
19
  def play_loop
20
20
  loop do
21
21
  if continuous_play && !playing?
22
- p "Playing random song"
22
+ p "Playing next song"
23
23
  play_next_song
24
24
  else
25
25
  sleep 0.1
@@ -28,7 +28,10 @@ module JimmyJukebox
28
28
  end
29
29
 
30
30
  def next_song
31
- @next_song ? @next_song : random_song
31
+ # reset @next_song each time it's accessed
32
+ current_next_song = @next_song ? @next_song : random_song
33
+ @next_song = random_song
34
+ current_next_song
32
35
  end
33
36
 
34
37
  def play_next_song
@@ -45,27 +48,37 @@ module JimmyJukebox
45
48
  end
46
49
 
47
50
  def previous_song
48
- @previous_song || nil
51
+ if songs_played.length >= 2
52
+ songs_played[songs_played.length-2]
53
+ else
54
+ nil
55
+ end
56
+ end
57
+
58
+ def songs_played
59
+ @songs_played ||= []
49
60
  end
50
61
 
51
62
  def replay_previous_song
52
- if previous_song
63
+ if previous_song && current_song
64
+ enable_continuous_play
65
+ self.next_song = previous_song
53
66
  p "Replaying #{previous_song.music_file}"
54
- #terminate_current_song
55
- play_song(previous_song)
67
+ current_song.terminate
68
+ self.current_song = nil
69
+ self.playing = false
56
70
  else
57
71
  raise NoPreviousSongException, "No previous song"
58
72
  end
59
73
  end
60
74
 
61
75
  def skip_song
62
- enable_continuous_play
63
76
  if current_song
77
+ enable_continuous_play
64
78
  p "Skipping #{current_song.music_file}"
65
79
  #play_random_song
66
- self.previous_song = current_song
80
+ current_song.terminate
67
81
  self.current_song = nil
68
- previous_song.terminate
69
82
  self.playing = false
70
83
  else
71
84
  raise NoCurrentSongException, "No current_song"
@@ -90,41 +103,39 @@ module JimmyJukebox
90
103
  end
91
104
 
92
105
  def play_random_song
93
- p "Inside play_random_song"
94
106
  play_song(random_song)
95
107
  end
96
108
 
97
109
  def enable_continuous_play
98
110
  self.continuous_play = true
99
- p "Enabled continuous_play"
100
111
  end
101
112
 
102
113
  def disable_continuous_play
103
114
  self.continuous_play = false
104
- p "Disabled continuous_play"
105
115
  end
106
116
 
107
117
  def play_song(song)
108
- terminate_current_song if current_song
109
118
  self.playing = true
110
- p "Setting current_song = #{song.music_file}"
119
+ terminate_current_song(play_another: false) if current_song
111
120
  self.current_song = song
121
+ self.songs_played << song
112
122
  current_song.play(user_config, self)
113
123
  p "Finished playing"
114
- self.previous_song = current_song
124
+ p "Songs played: " + songs_played.to_s
115
125
  self.current_song = nil
116
126
  self.playing = false
117
127
  rescue Song::SongTerminatedPrematurelyException
118
128
  p "Song ended prematurely"
119
129
  end
120
130
 
121
- def terminate_current_song
131
+ def terminate_current_song(opts=nil)
132
+ # By default, stops song and lets a new song play automatically
133
+ # To prevent another song from playing automatically, pass "play_another: false"
122
134
  if current_song
123
135
  p "Terminating #{current_song.music_file}"
124
136
  current_song.terminate
125
- self.previous_song = current_song
126
137
  self.current_song = nil
127
- self.playing = false
138
+ self.playing = (opts && opts[:play_another]) ? !play_another : false
128
139
  else
129
140
  raise NoCurrentSongException, "No current_song"
130
141
  end
@@ -37,16 +37,15 @@ module JimmyJukebox
37
37
  gpid == 0 ? nil : gpid
38
38
  end
39
39
 
40
+ def process_group_id
41
+ Process.getpgid(playing_pid)
42
+ end
43
+
40
44
  def pause
41
45
  self.paused = true
42
- # jruby doesn't seem to handle system() correctly
43
- # trying backticks
44
- # system("kill -s STOP #{playing_pid}") if playing_pid
45
46
  if grandchild_pid
46
- p "Pausing"
47
47
  `kill -s STOP #{grandchild_pid}`
48
48
  elsif playing_pid
49
- p "Pausing"
50
49
  `kill -s STOP #{playing_pid}`
51
50
  else
52
51
  raise NoPlayingPidException, "*** Can't pause song because can't find playing_pid #{playing_pid} ***"
@@ -55,14 +54,9 @@ module JimmyJukebox
55
54
 
56
55
  def unpause
57
56
  self.paused = false
58
- # jruby doesn't seem to handle system() correctly
59
- # trying backticks
60
- #system("kill -s CONT #{playing_pid}") if playing_pid
61
57
  if grandchild_pid
62
- p "Unpausing"
63
58
  `kill -s CONT #{grandchild_pid}`
64
59
  elsif playing_pid
65
- p "Unpausing"
66
60
  `kill -s CONT #{playing_pid}`
67
61
  else
68
62
  raise NoPlayingPidException, "*** Can't unpause song because can't find playing_pid #{playing_pid} ***"
@@ -77,17 +71,11 @@ module JimmyJukebox
77
71
  p "killed #{grandpid}"
78
72
  end
79
73
  `kill #{playpid}`
80
- p "killed #{playpid}"
81
74
  end
82
75
 
83
76
  def terminate
84
77
  self.paused = false
85
- #`killall #{player}`
86
78
  self.player = nil
87
- # killing processes seems problematic in JRuby
88
- # I've tried several approaches, and nothing seems reliable
89
- #Process.kill("SIGKILL",playing_pid) if playing_pid
90
- #Process.kill("SIGTERM",playing_pid) if playing_pid
91
79
  if playing_pid
92
80
  kill_playing_pid_and_children
93
81
  self.playing_pid = nil
@@ -118,38 +106,24 @@ module JimmyJukebox
118
106
  music_file_path = File.expand_path(music_file)
119
107
  run_command(player, music_file_path)
120
108
  p "playing_pid = " + playing_pid.to_s
121
- #system_yield_pid(player, music_file_path) do |pid|
122
- # self.playing_pid = pid
123
- #end
124
- #if running_jruby?
125
- Process.waitpid(playing_pid) # Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object
126
- #else
127
- # Process::waitpid(playing_pid)
128
- #end
129
- p "Stopped waiting"
109
+ Process.waitpid(playing_pid) # Waits for a child process to exit, returns its process id, and sets $? to a Process::Status object
130
110
  $? # return Process::Status object with instance methods .stopped?, .exited?, .exitstatus
131
111
  end
132
112
 
133
113
  end
134
114
 
135
- def running_jruby?
136
- defined?(JRUBY_VERSION) || RUBY_ENGINE == 'jruby' || RUBY_PLATFORM == 'java'
137
- end
138
-
139
115
  def run_command(command, arg)
140
- if running_jruby?
116
+ # make system call and get pid so you can pause/terminate process
117
+ if $running_jruby
141
118
  pid = Spoon.spawnp(command,arg)
142
119
  else
143
120
  begin
144
121
  pid = POSIX::Spawn::spawn(command + ' ' + arg)
145
- #pgid = Process.getpgid(pid)
146
- #child = POSIX::Spawn::Child.new(command + ' ' + arg)
147
- #pid = child.status.pid
148
122
 
149
- # create and run block in subprocess (which will terminate with status 0), capture subprocess pid
123
+ # posix/spawn is much faster than fork-exec
150
124
  #pid = Process.fork do
151
- # exec(command + ' ' + arg) # replace new process with system call
152
- # exit! 127 # exit process and return exit status 127; should never be reached
125
+ # exec(command + ' ' + arg)
126
+ # exit! 127 # should never be reached
153
127
  #end
154
128
  rescue NotImplementedError
155
129
  raise CannotSpawnProcessException, "*** Cannot play music because we found neither Spoon.spawnp (for JRuby) nor Process.fork (for MRI) ***"
@@ -158,26 +132,4 @@ module JimmyJukebox
158
132
  self.playing_pid = pid
159
133
  end
160
134
 
161
- # make system call and get pid so you can terminate process
162
- def system_yield_pid(command,arg)
163
- # would like to use Process.respond_to?(:fork) but JRuby mistakenly returns true
164
- if running_jruby?
165
- pid = Spoon.spawnp(command,arg)
166
- else
167
- begin
168
- #spawn(command + ' ' + arg)
169
- #pid = POSIX::Spawn::spawn(command + ' ' + arg)
170
-
171
- # create and run block in subprocess (which will terminate with status 0), capture subprocess pid
172
- pid = Process.fork do
173
- exec(command + ' ' + arg) # replace new process with system call
174
- exit! 127 # exit process and return exit status 127; should never be reached
175
- end
176
- rescue NotImplementedError
177
- raise CannotSpawnProcessException, "*** Cannot play music because we found neither Spoon.spawnp (for JRuby) nor Process.fork (for MRI) ***"
178
- end
179
- end
180
- yield pid if block_given? # call block, passing in the subprocess pid
181
- end
182
-
183
135
  end
@@ -51,7 +51,7 @@ user_input_thread = Thread.new do
51
51
  rescue Interrupt, SystemExit => e
52
52
  p "JimmyJukebox closed by user request. Bye!"
53
53
  jj.quit
54
- system('stty', stty_save) unless RUBY_ENGINE == 'jruby' # Restore original terminal state
54
+ system('stty', stty_save) unless $running_jruby # Restore original terminal state
55
55
  exit
56
56
  end
57
57
  end
@@ -1,4 +1,4 @@
1
1
  module JimmyJukebox
2
- VERSION = '0.4.1'
2
+ VERSION = '0.4.2'
3
3
  DATE = '2013-02-22'
4
4
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: jimmy_jukebox
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.1
5
+ version: 0.4.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - James Lavin