Class: Charming::Audio::Player
- Inherits:
-
Object
- Object
- Charming::Audio::Player
- Defined in:
- lib/charming/audio/player.rb
Overview
Player plays a single sound file by spawning a system audio binary, and exposes ‘stop`/`playing?`/`wait` to manage the child process. It never blocks the event loop on its own — call #play for fire-and-forget playback, or drive it from a controller `run_task` (spawn + #wait, with an `ensure player.stop`) to get a completion event and reliable teardown when the app quits.
A backend binary is resolved on first use, in priority order: ‘ffplay` (from ffmpeg) on every platform, then OS-native players (`afplay` on macOS; `paplay`, `mpg123`, `aplay` on Linux). Unavailable is raised when none are installed.
Defined Under Namespace
Classes: Unavailable
Constant Summary collapse
- BACKENDS =
Candidate backends in resolution order. ‘:os` is `:any`, `:macos`, or `:linux`; `:args` are inserted before the file path in the spawned command.
[ {command: "ffplay", os: :any, args: ["-nodisp", "-autoexit", "-loglevel", "quiet"]}, {command: "afplay", os: :macos, args: []}, {command: "paplay", os: :linux, args: []}, {command: "mpg123", os: :linux, args: ["-q"]}, {command: "aplay", os: :linux, args: ["-q"]} ].freeze
Instance Method Summary collapse
-
#available? ⇒ Boolean
True when a backend binary is installed for this platform.
-
#initialize(system: System.new) ⇒ Player
constructor
system is the OS adapter used to probe ‘PATH` and spawn/track the player process.
-
#play(path) ⇒ Object
Plays the sound file at path, stopping any sound already in progress first.
-
#playing? ⇒ Boolean
True while a spawned sound is still playing.
-
#stop ⇒ Object
Stops the current sound (if any), terminating and reaping the child process.
-
#wait ⇒ Object
Blocks until the current sound finishes, then clears it.
Constructor Details
#initialize(system: System.new) ⇒ Player
system is the OS adapter used to probe ‘PATH` and spawn/track the player process. The default talks to the real OS; specs inject a fake.
32 33 34 35 |
# File 'lib/charming/audio/player.rb', line 32 def initialize(system: System.new) @system = system @pid = nil end |
Instance Method Details
#available? ⇒ Boolean
True when a backend binary is installed for this platform. Lets callers degrade gracefully (e.g. skip a chime) instead of rescuing Unavailable.
73 74 75 |
# File 'lib/charming/audio/player.rb', line 73 def available? !backend.nil? end |
#play(path) ⇒ Object
Plays the sound file at path, stopping any sound already in progress first. Spawns the resolved backend and returns the child PID. Raises Unavailable when no backend binary is installed for this platform.
40 41 42 43 44 |
# File 'lib/charming/audio/player.rb', line 40 def play(path) backend = resolve_backend! stop if @pid = @system.spawn([backend[:command], *backend[:args], path.to_s]) end |
#playing? ⇒ Boolean
True while a spawned sound is still playing.
57 58 59 |
# File 'lib/charming/audio/player.rb', line 57 def !@pid.nil? && @system.alive?(@pid) end |
#stop ⇒ Object
Stops the current sound (if any), terminating and reaping the child process. Safe to call when nothing is playing.
48 49 50 51 52 53 54 |
# File 'lib/charming/audio/player.rb', line 48 def stop return unless @pid @system.terminate(@pid) @system.wait(@pid) @pid = nil end |
#wait ⇒ Object
Blocks until the current sound finishes, then clears it. Intended for use inside a background ‘run_task`. If the task thread is killed mid-wait (e.g. on app shutdown), `@pid` is left intact so an `ensure player.stop` can reap the child.
64 65 66 67 68 69 |
# File 'lib/charming/audio/player.rb', line 64 def wait return unless @pid @system.wait(@pid) @pid = nil end |