
Okay, you want to poll to see if the sound is still playing... This is not very easy to do... You really want to use the low-buffer callback from the soundcard driver to load the next sample into the buffer using DMA. (IE you can pass a function to the driver to call when you sample has been copied completely to the sound-cards memory). This is the way to do it... play_then_free = do set_callback (free_sample my_sample) play_sample my_sample You can see that this provides the interface you want to the user (IE samples are freed once they are finished with)... Keean. Sebastian Sylvan wrote:
On Thu, 16 Dec 2004 09:46:34 +0000, Keean Schupke
wrote: What about using a StablePtr? If you're dealing with hardware you would get the end-of-sample interrupt to free the buffer... Either way you either have to delay GC until the sample playback has finished... (well technically until the soundcard DMA has transferred the sample to the soundcards onboard memory) or free the memory when playback has finished. These ammount to the same thing... but using a StablePtr and explicit free seems much nicer than hacking strange stuff into a finalizer.
Explicitly freeing works as it is. I was just hoping to get a higher level abstraction on top of this so that the user could just create a sound resource, and then play it back all over the place (even in functions with short-lifespans) and have the system "Do The Right Thing" with regards to cleaning up once nothing references the sound resource, or the channels playing it, anymore.. Of couse, as stated, the problem comes in with the fact that channels will get cleaned up even if they are currently playing stuff. It would be ideal if one could just attatch a "guard" against the GC to a value so that each time the GC wants to collect unreferenced stuff it will first apply the guard-function, if there is one, to the value and only free it up if that returns True (this would be tested every time the GC does a "collection sweep").
Then I could just do something like the following each time a playback is started:
attatchGCGuard playback isPlaying
where: isPlaying :: Playback -> IO Bool attatchGCGuard :: a -> (a -> IO Bool) -> IO ()
This would mean that the playback won't get cleaned up if it's currently playing something. And since the Playback value has a reference to the "ForeignPtr CSoundSample" where the sound data lies, that won't get freed up either (freeing of that resource happens in the finalizer for that ForeignPtr).
Maybe that's not possible for reasons beyond my understanding, but perhaps it illustrates my problem in a clearer way.
/S