Sun audio blocks, even when run in a thread
Chris Liechti
cliechti at gmx.net
Mon Dec 1 16:17:16 EST 2003
[posted and mailed]
Bruce.Bon at SubaruTelescope.org (Bruce Bon) wrote in
news:184d1516.0311281857.4f6a8a8a at posting.google.com:
> The class below is intended to play a Sun audio file (.au) in the
> background while the main thread, which is servicing a GUI, continues
> without impact. It doesn't work. For a sound file that takes 3-5
> seconds to play, the main thread hangs for that long. I have run this
> many times, with changes in printouts and insertion of strategic
> sleeps to try to make sure that the player thread gives up control,
> but apparently the call to audioObj.write( audioString ) is atomic --
> NOTHING happens in the main thread until it returns. I have tested
> this with print statements and sleeps in the main thread instead of a
> GUI, and you can see the program's output simply halt while the sound
> is audible. I have also looked for delays at dataLock.acquire() and
> not found any.
>
> Help, suggestions, explanation or work-around??
no sorry, not for your problem directly...
_if_ there is a bug in the python module. it maybe, if the sunaudiodev is
implemented in C and forgets to release the GIL during the io operation.
altough i doubt it somehow, bugs in python itself are rare....
but, i can comment on your code ;-)
look at the module "Queue" that would save you the lock and all its
problems if you doo it manualy. it has also a get() function that can
block, so you dont need your poll loop with a sleep.
if you insist on using locks, consider try: ... finally: clasues, with
lock.release() in the finally block, so that you dont produce a deadlock,
even on exceptions.
i always use the "threading" module. its much cleaner in my option. i have
seen you tried it too :-)
chris
> import time
> import sunaudiodev
> from thread import *
>
> class AudioPlayer:
>
> def __init__( self, owner ):
> '''Constructor.'''
> self.soundQueue = []
> self.terminateFlag = False
> self.dataLock = allocate_lock()
> print 'AudioPlayer: starting playerThread...'
> print ' main thread ID = ', get_ident()
> self.playerThread = start_new_thread( self.__playerThread, ()
> )
>
>
> def playAudio( self, audio ):
> self.dataLock.acquire()
> self.soundQueue.append( audio ) # put to end of list
> self.dataLock.release()
>
> def terminate( self ):
> self.dataLock.acquire()
> self.terminateFlag = True
> self.dataLock.release()
> time.sleep(1)
>
> def __playerThread( self ):
> '''Function to be executed in background thread, to play
> sounds.'''
> print '__playerThread() starting: ID = ', get_ident()
> while True:
> # Check terminateFlag and soundQueue
> audio = None
> self.dataLock.acquire()
> if self.terminateFlag:
> self.dataLock.release()
> print '__playerThread(): terminating playerThread...'
> exit()
> l = len(self.soundQueue)
> if l > 0:
> audio = self.soundQueue.pop(0) # get from beginning
> of list
> self.dataLock.release()
>
> if audio == None:
> time.sleep( 1.0 ) # poll queue 1/second
> else:
> # Read the .au file
> auReadObj = open( audio, 'r' )
> audioString = auReadObj.read()
> auReadObj.close()
>
> # Open the audio device and play the sound
> try:
> audioObj = sunaudiodev.open('w')
> except sunaudiodev.error:
> print 'ERROR __playerThread: ' + \
> 'Failed to open Sun audio device.'
> else:
> audioObj.write( audioString )
> audioObj.close()
--
Chris <cliechti at gmx.net>
More information about the Python-list
mailing list