[CM] stop-playing-hook problem

Bill Schottstaedt bil@ccrma.Stanford.EDU
Mon, 24 May 2004 03:44:00 -0700

 > Now I pressed the GO button again.
 > The violine plays again in a loop.

There are two related problems here.  In several files, add-hook!
is called whenever that file is loaded, so if the file is loaded
twice, the hook gets two copies of the added hook function.  This can
be avoided by adding (if (not (defined...)))  around the
load-from-path calls (for example, in snd_conffile, many of the dlp
files are loaded, but they may already have been loaded).  Or we
could use hook-member (hooks.scm).  But currently there's little attempt to
protect against redundant functions on the hook list. If one such
hook is stop-playing-hook and it's getting a function that calls
(play) to loop, you get an explosion of plays (each time one stops, it
fires up two more).  This works anyway if you just load the dlp stuff,
but once snd_conffile.scm is also involved, several separate
stop-hooks start stepping on each other (play.scm's play-until-c-g
assumes it will be cancelled either via C-g or a function simulating that,
but other loopers aren't aware that something like that is sitting
on the hook).  So we shouldn't be using play-until-c-g in dlp/new-buttons.scm,
but that's just a bandaid.

I need to think of some way to make it safe to load these files any
number of times.  But, the harder problem is that a function that wants
to add a hook function has no way of knowing (in general) what else is
already on that hook's function list -- whether for example a looping
play is already queued up.  I think the whole start|stop-play|dac-hook
business needs to be redone.  So, I propose to add an argument to the
various play functions to associate a (stop-)function with that
particular "play" call, calling that function when that play finishes.
This way the various additions to the user interface can avoid accidental
"cross-talk", and there's no problem of "dangling" stop-hook entries.
I first thought it would be nice to accept a continuation in this context,
but I can't get it to work in Guile.

Then, eventually, remove stop-playing-channel|region|selection(?)-hook, and
start-playing-selection-hook(?) (since they can only cause confusion, I think).
Stop-dac-hook is still needed for handling level meters.  Start|stop-playing-hook is
needed for global GUI responses to reflect whether something is playing.
play-hook might be handled as another of the process-local or player-local

It seems that a similar problem could afflict the various open-sound hooks,
and the apply-control hooks, but in those cases, I think you could use
a sound-property to protect against this kind of error.