[Haskell-cafe] FFI woes!

Sebastian Sylvan sebastian.sylvan at gmail.com
Mon Dec 20 02:27:48 EST 2004


On Sat, 18 Dec 2004 20:24:47 -0500, Robert Dockins
<robdockins at fastmail.fm> wrote:
> 
> > Well that shouldn't affect the functionality. The weak pointer was
> > only a way of attatching a finalizer to the Playback object. It is
> > true that I should probably wrap up the the SoundPlaybackRaw inside
> > the SoundPlayback as well, to save CPU, but it shouldn't matter for
> > the core functionality.
> 
> I'm not sure I understand.
> 

Well not including the SamplePlaybackRaw in the SamplePlayback
datatype means that the SamplePlaybackRaw might get prematurely GC'd,
but if the finalizer had worked that wouldn't have mattered, it
would've only meant that the keep-alive loop might have been started
earlier.

Anyway, the reason for not wanting to do polling-loops was simply a
performance issue. FMOD is one of the fastest, if not THE fastest,
sound libraries out there so I didn't want to "ruin it" by attatching
too much extra "fluff".
That's why I wanted to start a polling loop ony when it was absolutely
necessary, ie only when the Playback object was being GC'd (which
meant that GC'ing of the sound data might be imminent).

But anyway, I decided to bite the bullet and do it "the easy way".
Here's the final, short-n-sweet (albeit slightly inefficient),
solution:


-- A playback of a sample resource
newtype SamplePlayback = SP (MVar CInt)

-- play, and keep data alive until playback is done
samplePlay' :: MVar CInt -> SoundSample -> IO ()
samplePlay' var s = do ch <- withForeignPtr s (fsound_PlaySound (-1))
                       putMVar var ch
                       let loop = do b <- isPlaying (SP var)
                                     case b of
                                       True -> do touchForeignPtr s
                                                  threadDelay 1000000
-- wait one second
                                                  loop
                                       False -> return ()		 
                       loop  

-- asynchronous playback action
samplePlay :: SoundSample -> IO SamplePlayback
samplePlay s = do var <- newEmptyMVar

		  -- spawn a new playback thread
                  forkIO (samplePlay' var s)
                
                  -- wait for the MVar to get filled in
                  let loop = do yield
                                b <- isEmptyMVar var
                                if b then loop else return ()
                  loop
                  return (SP var)


isPlaying :: SamplePlayback -> IO Bool
isPlaying (SP var) = do b <- withMVar var (fsound_IsPlaying)
		        return (cscharToBool b)  
		       

-- 
Sebastian Sylvan
+46(0)736-818655
UIN: 44640862


More information about the Haskell-Cafe mailing list