Skip to content

Instantly share code, notes, and snippets.

@ihollander
Last active August 14, 2020 20:22
Show Gist options
  • Save ihollander/61b194622b7a5389a581ed2a270d0641 to your computer and use it in GitHub Desktop.
Save ihollander/61b194622b7a5389a581ed2a270d0641 to your computer and use it in GitHub Desktop.
Ruby CLI Audio Player example using afplay
# How to play audio from the command line using afplay. Mac only!
# good reading on working with processes/forks: https://saveriomiroddi.github.io/Executing-and-killing-ruby-parallel-background-jobs/
# afplay: https://ss64.com/osx/afplay.html
# POSIX signals: https://man7.org/linux/man-pages/man7/signal.7.html
# Here's a simple example:
# play a song
process_id = spawn "afplay test.mp3"
# stop playing (make sure to use the same process_id returned by spawn)
Process.kill("SIGKILL", process_id)
# Here's a more advanced version of a class for managing afplay
class AudioPlayer
def initialize(file_path, options = {})
@command = file_path + build_options_string(options)
end
def play
if @process_id
# resume playing if the process is already running
Process.kill("SIGCONT", @process_id)
else
# start playing by running 'afplay'
# fork lets us returns a process_id we can use with other commands
@process_id = spawn "afplay #{@command}"
end
end
def pause
# send a stop signal to afplay using the process_id
Process.kill("SIGSTOP", @process_id)
end
def stop
# send a kill signal to aflpay using the process_id
Process.kill("SIGKILL", @process_id)
# detach the process
detach!
end
private
def build_options_string(options)
valid_options = %i(volume time rate quality)
options_string = ""
options.each do |key, value|
options_string += " -#{key[0]} #{value}" if valid_options.include?(key)
end
options_string
end
def detach!
# detaches process
Process.detach(@process_id)
# clear the process_id reference
@process_id = nil?
end
def inspect_process
# in case this is useful, this will print out the process id and status
p spawn "ps -O=S -p #{@process_id}"
end
end
# example usage
player = AudioPlayer.new("test.mp3", volume: 2, time: 10, rate: 0.5)
input = gets.chomp
while input != "exit"
case input
when "play"
player.play
when "pause"
player.pause
when "stop"
player.stop
end
input = gets.chomp
end
# cleanup
player.stop
# if your program doesn't exit cleanly:
# 1. run this command: ps -ax | grep afplay
# 2. look for the process id returned (first column of output), for example: 38062
# 3. kill the process manually: kill -9 38062
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment