Sebastian Sylvan wrote: >Ben Rudiak-Gould wrote: >>Why not spawn a thread which starts the playback, waits for it to >>finish, and then exits, and wrap the whole thread in a call to >>withForeignPtr? Then your finalizer won't be called prematurely. > >Well I could do this, but for one it would be cumbersome to stop >playback.
I don't think it is. Let me try to specify the problem precisely to make sure we're talking about the same thing. We have an interface something like this:
loadSong :: String -> IO (Ptr SongRep) playSong :: Ptr SongRep -> IO () stopPlaying :: Ptr SongRep -> IO () -- it will also stop by itself isPlaying :: Ptr SongRep -> IO Bool freeSong :: Ptr SongRep -> IO () -- unsafe if song is playing
and we want an interface like this:
loadSong' :: String -> IO Song playSong' :: Song -> IO () stopPlaying' :: Song -> IO () isPlaying' :: Song -> IO Bool
I think this implementation will work:
type Song = ForeignPtr SongRep
loadSong' name =
loadSong name >>= newForeignPtr freeSong playSong' song =
forkIO (withForeignPtr song (\s -> playSong s >> waitForSilence s)) waitForSilence s =
do threadDelay 500000
b <- isPlaying s
when b (waitForSilence s)stopPlaying' song = withForeignPtr song stopPlaying
isPlaying' song = withForeignPtr song isPlaying
If you need the return value from playSong, this should also work:
playSong' song =
do rtn <- withForeignPtr song playSong
forkIO (withForeignPtr song waitForSilence)
return rtnBut this won't work, because the withForeignPtr call will return before the thread exits:
brokenPlaySong' song =
withForeignPtr song (\s -> playSong >> forkIO (waitForSilence s))
-- Ben
_______________________________________________ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
