I am writing a program that creates audio samples in an emacs
buffer, then sends them to an external program (sox) to play in
the background while I continue working with emacs. Part of the
code is roughly as follows:
The sound plays as expected, but process-send-region does not
return until about half a second before the sound finishes
playing. This means that if I send several minutes of audio,
emacs is stuck during all that time, which completely defeats the
purpose of an asynchronous process. Using process-send-string
instead of process-send-region makes no difference.
I suppose it has to do with buffering on the pipe, bit I don't
know if I have any control over this. I tried to use stdbuf, as in:
(start-process "my-process" nil "stdbuf" "-i10M" "-o10M" "sox" ...
which makes no difference.
One possible approach would be to send the data in small chunks,
arranging for some sort of sentinel to be called when a chunk has
been consumed, to send the nex one. Is there any way to do this?
I could also write the data into a temporary file and let sox
read from it but that seems pretty inefficient and would require
careful cleanup to not clutter the disk.
The solution I found is to use a synchronous process:
(call-process-region start end "sox" nil 0 nil ...
where the fifth argument 0 means to discard process output and
not wait for completion. This works and does essentially what I
want, except that I don't know the PID of the spawned process so
I cannot communicate with it, e.g. to stop it before the end or
determine whether it's still runnin or not.