in reply to Killing a child process

I need to be able to stop the sound before reaching the end of the sound file.

SoX also has the trim operation:

$ play "/home/myname/soundfile.wav" trim 0 5

Should play only the first 5 seconds of your file.

Replies are listed 'Best First'.
Re^2: Killing a child process
by Anonymous Monk on Oct 03, 2017 at 08:13 UTC

    I checked the SoX documentation for stuff like that, but I need to stop the sound playback 'on demand'; I don't know in advance when the playback will be stopped.

      Ah, I see. I like offloading things like this to modules, in this case I think IPC::Run would be appropriate, the following works for me. If you think the child might misbehave and not terminate on SIGINT, see the IPC::Run doc section "Timeouts and Timers" on how to time out the kill operation.

      use IPC::Run qw/start/; my $h = start ['play','-q','/home/myname/soundfile.wav']; sleep 5; $h->signal('INT'); $h->finish;

        I wonder if there's any way to check that the sound file is still playing?

        I checked $h{STATE}, but its value only changes from 2 to 3 once we apply the $h->signal('INT')

        I also considered piping the output into a text file, and checking it periodically, since SoX displays a nice 'Done' when the sound file finishes playing. However, that won't help us if the end user specifies an audio package other than SoX.

        (This is a reply to Re^5)

        Your suggestions have provided the right answer! Here are two scripts; the first hangs until the sound file stops playing, and then displays a confirmation message.

        #!/usr/bin/perl use strict; use diagnostics; use warnings; use IPC::Run qw/start/; use POSIX ":sys_wait_h"; my ($h, $pid, $result); # Play the sound file $h = start ['play','-q','/home/ra/Desktop/trek3.mp3']; # Get the process ID (there's only one) foreach my $kid (@{ $h->{KIDS} }) { $pid = $kid->{PID}; } # Wait for the sound file to stop playing, and then display a message # Option 1: scripts hangs, and then correctly displays a message # as soon as the sound file stops playing sleep 5; waitpid($pid, 0); print "finished!\n"; # Tidy up $h->signal('INT'); $h->finish;

        The second checks once a second, and prints a confirmation message within a second of the sound file stopping.

        #!/usr/bin/perl use strict; use diagnostics; use warnings; use IPC::Run qw/start/; use POSIX ":sys_wait_h"; my ($h, $pid, $result); # Play the sound file $h = start ['play','-q','/home/ra/Desktop/trek3.mp3']; # Get the process ID (there's only one) foreach my $kid (@{ $h->{KIDS} }) { $pid = $kid->{PID}; } # Wait for the sound file to stop playing, and then display a message # Option 2: correctly displays a message within a second of the sound # file stopping playing do { sleep 1; waitpid($pid, WNOHANG); print "waiting...\n"; } until (! (kill 0, $pid)); print "finished!\n"; # Tidy up $h->signal('INT'); $h->finish;