jimmy_jukebox 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/play_jukebox CHANGED
@@ -1,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