sending data to an asynchronous process

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

sending data to an asynchronous process

Nicolas Graner-3
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:

(setq process
      (let ((process-connection-type nil))
        (start-process "my-process" nil
                       "sox" "-r" rate "-c" channels "-b" bits "-e" encoding "-q" "-d")))
(process-send-region process start end)
(process-send-eof process)

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.

I'd appreciate any insights and/or solutions?

FYI, running emacs 28.0.50 on debian 5.5.