Sun audio blocks, even when run in a thread

B

Bruce Bon

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??

Thanks.

Bruce Bon

_______________________________

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()
 
B

Bruce Bon

I converted this module to using threading instead of thread -- same behavior.
 
C

Chris Liechti

[posted and mailed]

(e-mail address removed) (Bruce Bon) wrote in
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()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top