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