The crashes persist with 1.8.1release ( downloaded from the pygame link, unistall 1.8.1.rc3, verified site-packages/pygame disapeared, installed 1.8.1release, run the tests that come with the docs, all passed OK)
A workaround enought good for me:
Instehad of calling directly pygame.mixer.music.play, I stop the music, then wait till pygame.mixer.music is not busy, then wait 0.1 second, finally play the new song. Yeah, clunky, but better than a crash !
Attached are the tests modified to use the workaround; you can look at the code for the details.
Warn: 50 runs with 50 changes take some time.
Also, I noticed that getting sample data files from sourceforge can be inconvenient at present time ( there are migrating datacenter ) so in the short time you can get the files from
http://rapidshare.com/files/134104315/media_test_claxo.rar.html
The stats where:
**** pygame 1.7.1
using clock.tick(50) - using mode0 ( no wait after unbusy )
initial song: 0
change mode is toggle: 1
time_sleep: 0.5
runs: 50
changes per runs: 50
success: 42
failed: 8
using clock.tick(50) - using mode1 ( wait 0.1 sec after unbusy)
initial song: 0
change mode is toggle: 1
time_sleep: 0.5
runs: 50
changes per runs: 50
success: 50
failed: 0
**** pygame 1.8.1release
clock.tick(50) , using mode0 (no wait after unbusy)
initial song: 0
change mode is toggle: 1
time_sleep: 0.5
runs: 50
changes per runs: 50
success: 50
failed: 0
clock.tick(50) - using mode1 ( wait 0.1 sec after unbusy)
initial song: 0
change mode is toggle: 1
time_sleep: 0.5
runs: 50
changes per runs: 50
success: 50
failed: 0
# begin file mtest2b.py
import pygame
import pygame.mixer
import time
##key1 : togle song
##key2 : reload same song
##key3 : quit
qsong = None
qvol = None
qmusic_state = 0 # 0: not in transition 1: waiting not busy 2: waiting 1 sec delay
qtime = None
def play_music( song, musicVol ):
global qsong, qvol, qmusic_state
tmp = pygame.mixer.music.get_busy()
print 'busy:',tmp,' ==0?:',tmp==0
if pygame.mixer.music.get_busy():
qsong = song
qvol = musicVol
qmusic_state = 1
stop_music()
else:
print '*** unbusy ***'
_play_music( song, musicVol )
def _play_music( song, musicVol ):
print 'About to start song:',song
pygame.mixer.music.set_volume(musicVol*0.01)
pygame.mixer.music.load( song )
pygame.mixer.music.play(-1) # looped
def stop_music():
if pygame.mixer.get_init():
pygame.mixer.music.stop()
def play_music_delayed1(): # wait some time after unbusy
global qmusic_state, qtime
if not qmusic_state:
return
if pygame.mixer.music.get_busy():
return
if qmusic_state == 1:
qtime = time.time()+0.1 # wait 0.1 sec after unbusy
qmusic_state = 2
else:
if qtime<time.time():
print '---delayed kicks in the song'
_play_music(qsong, qvol)
qmusic_state = 0
def play_music_delayed0(): # play when unbusy
global qmusic_state
if not qmusic_state:
return
if pygame.mixer.music.get_busy():
print 'wait...'
return
if qmusic_state == 1:
print '---delayed kicks in the song'
_play_music(qsong, qvol)
qmusic_state = 0
pygame.display.init()
pygame.mixer.init(44100, -16, True, 4096)
pygame.mixer.set_num_channels(8)
soundVol = 100
musicVol = 100
songs = ['menu.xm', 'egyptian-trance.xm']
selected = 0
print """
\nUse:
\t t: toggle song
\t r: restart song
\t esc: quit
"""
pygame.display.set_mode((300,300))
screen = pygame.display.get_surface()
screen.fill((0,0,255))
clock = pygame.time.Clock()
print 'pygame.mixer.music.get_busy():',pygame.mixer.music.get_busy()
print 'pygame.mixer.music.get_busy():',pygame.mixer.music.get_busy()
print 'pygame.mixer.music.get_busy():',pygame.mixer.music.get_busy()
bContinue = True
while bContinue:
# pygame.event.pump()
for ev in pygame.event.get():
if (ev.type == pygame.KEYDOWN):
if ev.key == pygame.K_ESCAPE:
bContinue = False
elif ev.key == pygame.K_t:
selected = not selected
play_music( songs[selected], musicVol)
elif ev.key == pygame.K_r:
play_music( songs[selected], musicVol)
else:
pass
play_music_delayed1()
pygame.display.update()
clock.tick(25)
pygame.quit()
# end file mtest2b.py
#begin file mtest4b.py
import pygame
import pygame.mixer
import sys, time
import subprocess
qsong = None
qvol = None
qmusic_state = 0 # 0: not in transition 1: waiting not busy 2: waiting delay after unbusy
qtime = None
def play_music( song, musicVol ):
global qsong, qvol, qmusic_state
tmp = pygame.mixer.music.get_busy()
print 'busy:',tmp,' ==0?:',tmp==0
if pygame.mixer.music.get_busy():
qsong = song
qvol = musicVol
qmusic_state = 1
stop_music()
else:
print '*** unbusy ***'
_play_music( song, musicVol )
def _play_music( song, musicVol ):
print 'About to start song:',song
pygame.mixer.music.set_volume(musicVol*0.01)
pygame.mixer.music.load( song )
pygame.mixer.music.play(-1) # looped
def stop_music():
if pygame.mixer.get_init():
pygame.mixer.music.stop()
def play_music_delayed1(): # wait some time after unbusy
global qmusic_state, qtime
if not qmusic_state:
return
if pygame.mixer.music.get_busy():
return
if qmusic_state == 1:
qtime = time.time()+0.1 # wait 0.1 sec after unbusy
qmusic_state = 2
else:
if qtime<time.time():
print '---delayed kicks in the song'
_play_music(qsong, qvol)
qmusic_state = 0
def play_music_delayed0(): # play when unbusy
global qmusic_state
if not qmusic_state:
return
if pygame.mixer.music.get_busy():
print 'wait...'
return
if qmusic_state == 1:
print '---delayed kicks in the song'
_play_music(qsong, qvol)
qmusic_state = 0
ch_per_run = 0
try:
ch_per_run = int(sys.argv[1])
bToggle = int(sys.argv[2])
selected = int(sys.argv[3])
except:
pass
if ch_per_run<1:
print """
Usage:
\tmtest3.py n b s
Where:
\tn > 1 Number of changes to try
\tb = 0-1 1->toggle songs, 0->restart song
\ts = 0-1 starting song, 0->menu.xm , 1->egyptian-trance.xm
"""
sys.exit(1)
pygame.display.init()
pygame.mixer.init(44100, -16, True, 4096)
pygame.mixer.set_num_channels(8)
soundVol = 100
musicVol = 100
songs = ['menu.xm', 'egyptian-trance.xm']
chtime = time.time()+1.0
play_music( songs[selected], musicVol)
if bToggle:
selected = not selected
pygame.display.set_mode((300,300))
screen = pygame.display.get_surface()
screen.fill((0,0,255))
clock = pygame.time.Clock()
cntChanges = 0
bContinue = True
while bContinue:
# pygame.event.pump()
for ev in pygame.event.get():
if (ev.type == pygame.KEYDOWN):
if ev.key == pygame.K_ESCAPE:
bContinue = False
if time.time()>chtime:
chtime = time.time() + 1.0
play_music( songs[selected], musicVol)
if bToggle:
selected = not selected
cntChanges += 1
if cntChanges > ch_per_run:
bContinue = False
play_music_delayed1()
pygame.display.update()
clock.tick(50) # was 25 on 1st series
pygame.quit()
f = open('tstats.txt','a')
f.write('run completed\n')
f.close()
sys.exit(7)
#end file mtest4b.py
#begin file trunner2b.py
import subprocess, time
# params test run
maxruns = 50
ch_per_run = 50
#
bToggle = 1
initial_song = 0
time_sleep = 0.5 # use None for no sleep beetwen runs
cntruns = 0
cntfailed = 0
#clean stats
f = open('tstats.txt','w')
f.write('Start.\n')
f.close()
sl = ['python.exe','mtest4b.py','%d'%ch_per_run,'%d'%bToggle,'%d'%initial_song ]
for i in xrange(maxruns):
cntruns +=1
ret = subprocess.call(sl)
if time_sleep:
time.sleep(time_sleep)
f = open('tstats.txt','r')
cntsucces = len(f.readlines())-1
f.close()
print 'initial song:',initial_song
print 'change mode is toggle:',bToggle
print 'time_sleep:',time_sleep
print 'runs:', maxruns
print 'changes per runs:',ch_per_run
print 'success:',cntsucces
print 'failed:', maxruns-cntsucces
#end file trunner2b.py